this repo has no description

implement boxfighter #14

open opened by voigt.tngl.sh targeting main from add-boxfighter
Labels

None yet.

assignee

None yet.

Participants 1
AT URI
at://did:plc:6q572hlx7omtsszji5w2fyw3/sh.tangled.repo.pull/3mcabiw6cum22
+499
Diff #0
boxfighter/eg_6x10.fff

This is a binary file and will not be displayed.

+7
boxfighter/go.mod
··· 1 + module boxfighter 2 + 3 + go 1.25.0 4 + 5 + require github.com/firefly-zero/firefly-go v0.9.5 6 + 7 + require github.com/orsinium-labs/tinymath v1.0.0 // indirect
+4
boxfighter/go.sum
··· 1 + github.com/firefly-zero/firefly-go v0.9.5 h1:BzBr4t76bDVVFwNaWJixs1XasqLNBIdg0k9JXblBfU4= 2 + github.com/firefly-zero/firefly-go v0.9.5/go.mod h1:+X/XGyPdES51OESkV8NSf1mszEBZionoROM7x2pBofw= 3 + github.com/orsinium-labs/tinymath v1.0.0 h1:Uzp3GmjWIBxMObx4MQi9ACDu4Q8WKjSRakB1OMo9Bu0= 4 + github.com/orsinium-labs/tinymath v1.0.0/go.mod h1:WPXX6ei3KSXG7JfA03a+ekCYaY9SWN4I+JRl2p6ck+A=
+21
boxfighter/main.go
··· 1 + package main 2 + 3 + import ( 4 + "github.com/firefly-zero/firefly-go/firefly" 5 + ) 6 + 7 + var ( 8 + font firefly.Font 9 + ) 10 + 11 + func init() { 12 + firefly.Boot = boot 13 + firefly.Render = render 14 + } 15 + 16 + func boot() { 17 + } 18 + 19 + func render() { 20 + firefly.DrawText("x", font, firefly.Point{X: 100, Y: 100}, firefly.ColorDarkBlue) 21 + }
+131
boxfighter/tmp/box.go
··· 1 + package main 2 + 3 + import "github.com/firefly-zero/firefly-go/firefly" 4 + 5 + const ( 6 + boxWidth = 24 7 + boxHeight = 24 8 + 9 + g = 0.05 // Gravity (้‡ๅŠ›ๅŠ ้€Ÿๅบฆ) ใฎ็•ฅ 10 + jump = -3.0 // ใ‚ธใƒฃใƒณใƒ—ๅŠ› 11 + ) 12 + 13 + // boxData represents the box character 14 + type boxData struct { 15 + x float32 16 + y float32 17 + vy float32 // Velocity of y (้€Ÿๅบฆใฎyๆˆๅˆ†) ใฎ็•ฅ 18 + 19 + w int 20 + h int 21 + } 22 + 23 + // newbox creates a new box 24 + func newBox() *boxData { 25 + return &boxData{ 26 + x: 10, 27 + y: 160 - 45, 28 + vy: 0, 29 + 30 + w: 15, 31 + h: 25, 32 + } 33 + } 34 + 35 + // reset resets the box's position for a new game 36 + func (gd *boxData) reset() { 37 + gd.x = 10 38 + gd.y = 10 39 + gd.vy = 0 40 + } 41 + 42 + // jump makes the box jump 43 + func (gd *boxData) jump() { 44 + gd.y += jump 45 + } 46 + 47 + func (gd *boxData) left() { 48 + gd.x -= 1 49 + } 50 + 51 + // jump makes the box jump 52 + func (gd *boxData) right() { 53 + gd.x += 1 54 + } 55 + 56 + // move moves the box 57 + func (gd *boxData) gravity() { 58 + if gd.y < 160-25 { 59 + gd.vy += g // ้€ŸๅบฆใซๅŠ ้€Ÿๅบฆใ‚’่ถณใ™ 60 + gd.y += gd.vy // ไฝ็ฝฎใซ้€Ÿๅบฆใ‚’่ถณใ™ 61 + } 62 + } 63 + 64 + // draw draws the box 65 + func (gd *boxData) draw() { 66 + firefly.DrawRect(firefly.Point{X: int(gd.x), Y: int(gd.y)}, firefly.Size{W: gd.w, H: gd.h}, firefly.Style{FillColor: firefly.ColorNone, StrokeColor: firefly.ColorBlack, StrokeWidth: 1}) 67 + } 68 + 69 + // position returns the box's position 70 + func (gd *boxData) position() (int, int, int, int) { 71 + l := int(gd.x) 72 + t := int(gd.y) 73 + r := int(gd.x) + boxWidth 74 + b := int(gd.y) + boxHeight 75 + 76 + return l, t, r, b 77 + } 78 + 79 + // // isHit returns true if the box is hit by a wall 80 + // func (gd *boxData) isHit(wl, wt, wr, wb int) bool { 81 + // gl, gt, gr, gb := gd.position() 82 + 83 + // if gr < wl || gl > wr { 84 + // return false 85 + // } 86 + 87 + // if gb < wt || gt > wb { 88 + // return false 89 + // } 90 + 91 + // return true 92 + // } 93 + 94 + // hitWalls returns true if the box hits any walls 95 + // func (gd *boxData) hitWalls(w *wallsData) bool { 96 + // for _, wall := range w.walls { 97 + // // ไธŠใฎๅฃใ‚’่กจใ™ๅ››่ง’ๅฝขใ‚’ไฝœใ‚‹ 98 + // bLeft, bTop, bRight, bBottom := wall.top() 99 + 100 + // // ไธŠใฎๅฃใจใฎๅฝ“ใŸใ‚Šๅˆคๅฎš 101 + // if gd.isHit(bLeft, bTop, bRight, bBottom) { 102 + // return true 103 + // } 104 + 105 + // // ไธ‹ใฎๅฃใ‚’่กจใ™ๅ››่ง’ๅฝขใ‚’ไฝœใ‚‹ 106 + // bLeft, bTop, bRight, bBottom = wall.bottom() 107 + 108 + // // ไธ‹ใฎๅฃใจใฎๅฝ“ใŸใ‚Šๅˆคๅฎš 109 + // if box.isHit(bLeft, bTop, bRight, bBottom) { 110 + // return true 111 + // } 112 + // } 113 + 114 + // return false 115 + // } 116 + 117 + // hitTop returns true if the box hits the top of the screen 118 + // func (gd *boxData) hitTop() bool { 119 + // return gd.y < 0 120 + // } 121 + 122 + // func (gd *boxData) hitBottom() bool { 123 + // b := int(gd.y) + boxHeight 124 + // return b > 160 125 + // } 126 + 127 + // score returns the current score of the player based on the box's position 128 + // func (gd *boxData) score(w *wallsData) int { 129 + // l, _, _, _ := gd.position() 130 + // return w.score(l) 131 + // }
+189
boxfighter/tmp/box2.go
··· 1 + package main 2 + 3 + const ( 4 + groundY = float32(screenH - 80) 5 + groundThickness = float32(80) 6 + 7 + // ---------- Tuning ---------- 8 + maxRunSpeed = float32(380) 9 + 10 + // Separate accel/decel 11 + groundAccel = float32(2600) 12 + groundDecel = float32(3200) 13 + airAccel = float32(1400) 14 + airDecel = float32(300) 15 + 16 + // Jump 17 + jumpSpeed = float32(640) 18 + 19 + // Variable jump height: cut velocity when releasing jump while going up 20 + jumpCutMultiplier = float32(0.35) 21 + 22 + // Coyote time + jump buffer (seconds) 23 + coyoteTime = float32(0.10) 24 + jumpBufferTime = float32(0.12) 25 + 26 + // --- Fast-fall tuning --- 27 + // Base gravity is used when rising (Vel.Y < 0) and jump is held. 28 + // When falling (Vel.Y > 0) we apply higher gravity (fallMultiplier). 29 + // When jump is released early during rise, we apply higher gravity too (lowJumpMultiplier). 30 + gravity = float32(1200) // "floatier" base on the way up 31 + fallMultiplier = float32(2.2) // faster fall 32 + lowJumpMultiplier = float32(2.6) // stronger pull-down if jump released early 33 + maxFallSpeed = float32(2200) // higher terminal velocity for snappy fall 34 + ) 35 + 36 + var dir float32 = 0.0 37 + 38 + type Vector2 struct { 39 + X float32 40 + Y float32 41 + } 42 + 43 + type Player struct { 44 + Pos Vector2 45 + Vel Vector2 46 + Size Vector2 47 + OnGround bool 48 + 49 + CoyoteTimer float32 50 + JumpBuffer float32 51 + Jumping bool 52 + } 53 + 54 + func clamp(v, min, max float32) float32 { 55 + if v < min { 56 + return min 57 + } 58 + if v > max { 59 + return max 60 + } 61 + return v 62 + } 63 + 64 + func approach(current, target, delta float32) float32 { 65 + if current < target { 66 + current += delta 67 + if current > target { 68 + return target 69 + } 70 + return current 71 + } 72 + if current > target { 73 + current -= delta 74 + if current < target { 75 + return target 76 + } 77 + return current 78 + } 79 + return current 80 + } 81 + 82 + func newPlayer() *Player { 83 + return &Player{ 84 + Pos: Vector2{X: 120, Y: groundY - 60}, 85 + Vel: Vector2{X: 0, Y: 0}, 86 + Size: Vector2{X: 50, Y: 60}, 87 + } 88 + } 89 + 90 + func (p *Player) jump() { 91 + _ = dir 92 + } 93 + 94 + func (p *Player) left() { 95 + dir -= 1 96 + } 97 + 98 + func (p *Player) right() { 99 + dir += 1 100 + } 101 + 102 + func GetFrameTime() float32 { 103 + return 1 / 60 104 + } 105 + 106 + func renderPlayer() { 107 + // Get time in seconds for last frame drawn (delta time) 108 + // float GetFrameTime(void); 109 + dt := GetFrameTime() 110 + 111 + // ---- Timers ---- 112 + if p.OnGround { 113 + p.CoyoteTimer = coyoteTime 114 + } else { 115 + p.CoyoteTimer = clamp(p.CoyoteTimer-dt, 0, 999) 116 + } 117 + 118 + if jumpPressed { 119 + p.JumpBuffer = jumpBufferTime 120 + } else { 121 + p.JumpBuffer = clamp(p.JumpBuffer-dt, 0, 999) 122 + } 123 + 124 + // ---- Horizontal movement (accel/decel) ---- 125 + if p.OnGround { 126 + if dir != 0 { 127 + target := dir * maxRunSpeed 128 + p.Vel.X = approach(p.Vel.X, target, groundAccel*dt) 129 + } else { 130 + p.Vel.X = approach(p.Vel.X, 0, groundDecel*dt) 131 + } 132 + } else { 133 + if dir != 0 { 134 + target := dir * maxRunSpeed 135 + p.Vel.X = approach(p.Vel.X, target, airAccel*dt) 136 + } else { 137 + p.Vel.X = approach(p.Vel.X, 0, airDecel*dt) 138 + } 139 + } 140 + p.Vel.X = clamp(p.Vel.X, -maxRunSpeed, maxRunSpeed) 141 + 142 + // ---- Jump using buffer + coyote ---- 143 + if p.JumpBuffer > 0 && p.CoyoteTimer > 0 { 144 + p.Vel.Y = -jumpSpeed 145 + p.OnGround = false 146 + p.CoyoteTimer = 0 147 + p.JumpBuffer = 0 148 + p.Jumping = true 149 + } 150 + 151 + // ---- Variable jump height (jump cut) ---- 152 + // Optional: keep it, feels good in addition to lowJumpMultiplier gravity. 153 + if jumpReleased && p.Jumping && p.Vel.Y < 0 { 154 + p.Vel.Y *= jumpCutMultiplier 155 + } 156 + 157 + // ---- Fast-fall gravity ---- 158 + // If falling: stronger gravity. 159 + // If rising but jump not held: stronger gravity (low jump). 160 + g := gravity 161 + if p.Vel.Y > 0 { 162 + g *= fallMultiplier 163 + } else if p.Vel.Y < 0 && !jumpHeld { 164 + g *= lowJumpMultiplier 165 + } 166 + p.Vel.Y += g * dt 167 + p.Vel.Y = clamp(p.Vel.Y, -100000, maxFallSpeed) 168 + 169 + // ---- Integrate ---- 170 + p.Pos.X += p.Vel.X * dt 171 + p.Pos.Y += p.Vel.Y * dt 172 + 173 + // ---- Ground collision ---- 174 + playerBottom := p.Pos.Y + p.Size.Y 175 + if playerBottom >= groundY { 176 + p.Pos.Y = groundY - p.Size.Y 177 + p.Vel.Y = 0 178 + p.OnGround = true 179 + p.Jumping = false 180 + } else { 181 + p.OnGround = false 182 + } 183 + 184 + // ---- Screen bounds (X) ---- 185 + p.Pos.X = clamp(p.Pos.X, 0, float32(screenW)-p.Size.X) 186 + if p.Pos.X == 0 || p.Pos.X == float32(screenW)-p.Size.X { 187 + p.Vel.X = 0 188 + } 189 + }
+73
boxfighter/tmp/keys.go
··· 1 + package main 2 + 3 + import ff "github.com/firefly-zero/firefly-go/firefly" 4 + 5 + // Check if a key is being pressed (key held down) 6 + // bool IsKeyDown(int key) 7 + // { 8 + // bool down = false; 9 + 10 + // if ((key > 0) && (key < MAX_KEYBOARD_KEYS)) 11 + // { 12 + // if (CORE.Input.Keyboard.currentKeyState[key] == 1) down = true; 13 + // } 14 + 15 + // return down; 16 + // } 17 + func IsKeyDown(buttons ff.Buttons) bool { 18 + var down bool 19 + 20 + if buttons.S == true { 21 + down = true 22 + } 23 + if buttons.E == true { 24 + down = true 25 + } 26 + if buttons.W == true { 27 + down = true 28 + } 29 + if buttons.N == true { 30 + down = true 31 + } 32 + if buttons.Menu == true { 33 + down = true 34 + } 35 + 36 + return down 37 + } 38 + 39 + // // Check if a key has been released once 40 + // bool IsKeyReleased(int key) 41 + // { 42 + // bool released = false; 43 + 44 + // if ((key > 0) && (key < MAX_KEYBOARD_KEYS)) 45 + // { 46 + // if ((CORE.Input.Keyboard.previousKeyState[key] == 1) && (CORE.Input.Keyboard.currentKeyState[key] == 0)) released = true; 47 + // } 48 + 49 + // return released; 50 + // } 51 + func IsKeyReleased(buttons, buttonsOld ff.Buttons) bool { 52 + var released bool 53 + 54 + if buttons.AnyPressed() == false { 55 + if buttonsOld.S == true && buttons.S == false { 56 + released = true 57 + } 58 + if buttonsOld.E == true && buttons.E == false { 59 + released = true 60 + } 61 + if buttonsOld.W == true && buttons.W == false { 62 + released = true 63 + } 64 + if buttonsOld.N == true && buttons.N == false { 65 + released = true 66 + } 67 + if buttonsOld.Menu == true && buttons.Menu == false { 68 + released = true 69 + } 70 + } 71 + 72 + return released 73 + }
+74
boxfighter/tmp/main copy.go
··· 1 + package main 2 + 3 + import ( 4 + "github.com/firefly-zero/firefly-go/firefly" 5 + ) 6 + 7 + const ( 8 + screenW = 240 9 + screenH = 160 10 + ) 11 + 12 + var ( 13 + frames = 0 14 + score = 0 15 + 16 + font firefly.Font 17 + p *Player 18 + 19 + buttons firefly.Buttons 20 + buttonsOld firefly.Buttons 21 + 22 + jumpPressed bool = false 23 + jumpHeld bool = false 24 + jumpReleased bool = false 25 + ) 26 + 27 + func init() { 28 + firefly.Boot = boot 29 + // firefly.Update = update 30 + firefly.Render = render 31 + } 32 + 33 + func boot() { 34 + p = newPlayer() 35 + } 36 + 37 + // func update() { 38 + // frames += 1 39 + 40 + // renderPlayer() 41 + // buttons = firefly.ReadButtons(firefly.Combined) 42 + // buttonsOld = firefly.ReadButtons(firefly.Combined) 43 + 44 + // jumpPressed = buttons.N 45 + // jumpHeld = buttons.Held(buttonsOld).N 46 + // jumpReleased = buttons.JustReleased(buttonsOld).N 47 + 48 + // if buttons.N { 49 + // p.jump() 50 + // } 51 + 52 + // if buttons.W { 53 + // p.left() 54 + // } 55 + 56 + // if buttons.E { 57 + // p.right() 58 + // } 59 + // } 60 + 61 + func render() { 62 + // firefly.ClearScreen(firefly.ColorWhite) 63 + 64 + // ff.DrawRect(ff.Point{X: 0, Y: int(groundY)}, ff.Size{W: screenW, H: int(groundThickness)}, ff.Style{FillColor: ff.ColorLightGray, StrokeColor: ff.ColorLightGray, StrokeWidth: 1}) 65 + // ff.DrawRect( 66 + // ff.Point{X: int(p.Pos.X), Y: int(p.Pos.Y)}, 67 + // ff.Size{W: int(p.Size.X), H: int(p.Size.Y)}, 68 + // ff.Style{FillColor: ff.ColorDarkBlue, StrokeColor: ff.ColorDarkBlue, StrokeWidth: 1}, 69 + // ) 70 + 71 + // firefly.DrawText("F: "+strconv.Itoa(frames), font, firefly.Point{X: 10, Y: 10}, firefly.ColorDarkBlue) 72 + firefly.DrawText("x", font, firefly.Point{X: 100, Y: 100}, firefly.ColorDarkBlue) 73 + // rl.DrawText("Move: A/D or Left/Right Jump: Space (buffer+coyote+variable+fast-fall)", 20, 20, 20, rl.Black) 74 + }

History

1 round 0 comments
sign up or login to add to the discussion
voigt.tngl.sh submitted #0
1 commit
expand
implement boxfighter
no conflicts, ready to merge
expand 0 comments