You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
4.0 KiB
Go
177 lines
4.0 KiB
Go
package component
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
|
|
"code.rocketnine.space/tslocum/boxbrawl/asset"
|
|
|
|
"github.com/hajimehoshi/ebiten/v2"
|
|
)
|
|
|
|
type PlayerAction int
|
|
|
|
const (
|
|
ActionIdle PlayerAction = iota
|
|
ActionStunned
|
|
ActionPunch
|
|
ActionKick
|
|
ActionBlock
|
|
ActionTaunt1
|
|
ActionTaunt2
|
|
ActionTaunt3
|
|
ActionTaunt4
|
|
)
|
|
|
|
type HitboxType int
|
|
|
|
const (
|
|
HitboxNone HitboxType = iota
|
|
HitboxNormal
|
|
HitboxHurt
|
|
)
|
|
|
|
type FrameData struct {
|
|
T HitboxType // Type
|
|
R image.Rectangle // Rect
|
|
S *ebiten.Image // Sprite
|
|
G int // Go to frame (for looping actions)
|
|
}
|
|
|
|
const PlayerSize = 16
|
|
|
|
const (
|
|
PlayerHeight = 48
|
|
PlayerWidth = 16
|
|
)
|
|
|
|
func RectTouches(r1 image.Rectangle, r2 image.Rectangle) bool {
|
|
return !r1.Empty() && !r2.Empty() &&
|
|
r1.Min.X <= r2.Max.X && r2.Min.X <= r1.Max.X &&
|
|
r1.Min.Y <= r2.Max.Y && r2.Min.Y <= r1.Max.Y
|
|
}
|
|
|
|
// stdHit returns FrameData using a standard hitbox and the provided sprite.
|
|
func stdHit(sprite *ebiten.Image) FrameData {
|
|
return FrameData{
|
|
T: HitboxNormal,
|
|
R: image.Rect(0, 0, PlayerWidth, PlayerHeight),
|
|
S: sprite,
|
|
}
|
|
}
|
|
|
|
// stdHitRange returns FrameData using a standard hitbox and the provided sprite range.
|
|
func stdHitRange(sprite *ebiten.Image, spriteX int, spriteY int, size int) []FrameData {
|
|
data := make([]FrameData, size)
|
|
for i := 0; i < size; i++ {
|
|
data[i] = stdHit(asset.FrameAt(asset.ImgPlayer, spriteX+i, spriteY))
|
|
}
|
|
return data
|
|
}
|
|
|
|
func FrameDataForActionTick(a PlayerAction, tick int) []FrameData {
|
|
actionFrames := AllPlayerFrames[a]
|
|
if tick-1 >= len(actionFrames) {
|
|
// Handle
|
|
if a == ActionStunned {
|
|
return AllPlayerFrames[ActionStunned][0]
|
|
}
|
|
return nil
|
|
}
|
|
return actionFrames[tick-1]
|
|
}
|
|
|
|
func FlipRect(r image.Rectangle, flip bool) image.Rectangle {
|
|
if !flip {
|
|
return r
|
|
}
|
|
return image.Rect(-r.Min.X+PlayerSize, r.Min.Y, -r.Max.X+PlayerSize, r.Max.Y)
|
|
}
|
|
|
|
func PlayerOnRightSide(p Player, o Player) bool {
|
|
return p.X > o.X
|
|
}
|
|
|
|
type Player struct {
|
|
X, Y float64
|
|
VX, VY float64
|
|
Color color.Color
|
|
PlayerNum int
|
|
|
|
Grounded bool
|
|
|
|
Action PlayerAction
|
|
ActionTicksLeft int
|
|
|
|
WalkFrame int
|
|
WalkFrameReverse bool
|
|
|
|
Crouching bool
|
|
CrouchFrame int
|
|
|
|
NoPunch bool
|
|
NoKick bool
|
|
|
|
PlayAgain bool
|
|
}
|
|
|
|
func (p *Player) String() string {
|
|
return fmt.Sprintf("Player %d: X:%f Y:%f Action: %d", p.PlayerNum, p.X, p.Y, p.Action)
|
|
}
|
|
|
|
func (p *Player) Clone() Player {
|
|
result := Player{}
|
|
result = *p
|
|
return result
|
|
}
|
|
|
|
func (p *Player) Walking() bool {
|
|
const walkThreshold = 0.2
|
|
return p.Grounded && p.Action == ActionIdle && (p.VX < -walkThreshold || p.VX > walkThreshold)
|
|
}
|
|
|
|
func TranslateRect(r image.Rectangle, x int, y int) image.Rectangle {
|
|
r.Min.X, r.Min.Y = r.Min.X+x, r.Min.Y+y
|
|
r.Max.X, r.Max.Y = r.Max.X+x, r.Max.Y+y
|
|
return r
|
|
}
|
|
|
|
// WalkFrames are defined in chronological order.
|
|
var WalkFrames = []*ebiten.Image{
|
|
asset.FrameAt(asset.ImgPlayer, 0, 13),
|
|
asset.FrameAt(asset.ImgPlayer, 1, 13),
|
|
asset.FrameAt(asset.ImgPlayer, 2, 13),
|
|
asset.FrameAt(asset.ImgPlayer, 3, 13),
|
|
asset.FrameAt(asset.ImgPlayer, 4, 13),
|
|
asset.FrameAt(asset.ImgPlayer, 5, 13),
|
|
asset.FrameAt(asset.ImgPlayer, 6, 13),
|
|
asset.FrameAt(asset.ImgPlayer, 7, 13),
|
|
}
|
|
|
|
// CrouchFrames are defined in chronological order.
|
|
var CrouchFrames = []*ebiten.Image{
|
|
asset.FrameAt(asset.ImgPlayer, 0, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 1, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 2, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 3, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 4, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 5, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 6, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 7, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 8, 14),
|
|
asset.FrameAt(asset.ImgPlayer, 9, 14),
|
|
}
|
|
|
|
// CrouchWalkFrames are defined in chronological order.
|
|
var CrouchWalkFrames = []*ebiten.Image{
|
|
asset.FrameAt(asset.ImgPlayer, 0, 15),
|
|
asset.FrameAt(asset.ImgPlayer, 1, 15),
|
|
asset.FrameAt(asset.ImgPlayer, 2, 15),
|
|
asset.FrameAt(asset.ImgPlayer, 3, 15),
|
|
asset.FrameAt(asset.ImgPlayer, 4, 15),
|
|
asset.FrameAt(asset.ImgPlayer, 5, 15),
|
|
asset.FrameAt(asset.ImgPlayer, 6, 15),
|
|
asset.FrameAt(asset.ImgPlayer, 7, 15),
|
|
}
|