Add mirror and block AI types
This commit is contained in:
parent
cf1be8e89d
commit
aba1cb30f5
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
@ -101,10 +101,6 @@ var AllPlayerFrames = [][][]FrameData{
|
|||
S: asset.FrameAt(asset.ImgPlayer, 0, 2),
|
||||
},
|
||||
},
|
||||
}, { // ActionBlock
|
||||
{
|
||||
// TODO
|
||||
},
|
||||
}, { // ActionPunch
|
||||
{
|
||||
{
|
||||
|
@ -153,6 +149,16 @@ var AllPlayerFrames = [][][]FrameData{
|
|||
{
|
||||
stdHit(asset.FrameAt(asset.ImgPlayer, 0, 1)),
|
||||
},
|
||||
}, { // ActionKick
|
||||
{
|
||||
// TODO
|
||||
},
|
||||
}, { // ActionBlock
|
||||
{
|
||||
stdHit(asset.FrameAt(asset.ImgPlayer, 0, 11)),
|
||||
}, {
|
||||
stdHit(asset.FrameAt(asset.ImgPlayer, 0, 11)),
|
||||
},
|
||||
}, { // ActionTaunt1
|
||||
{
|
||||
stdHit(asset.FrameAt(asset.ImgPlayer, 28, 4)),
|
||||
|
|
|
@ -15,8 +15,9 @@ type PlayerAction int
|
|||
const (
|
||||
ActionIdle PlayerAction = iota
|
||||
ActionStunned
|
||||
ActionBlock
|
||||
ActionPunch
|
||||
ActionKick
|
||||
ActionBlock
|
||||
ActionTaunt1
|
||||
ActionTaunt2
|
||||
ActionTaunt3
|
||||
|
|
58
game/game.go
58
game/game.go
|
@ -209,6 +209,14 @@ func (g *Game) ReadInputs() InputBits {
|
|||
in.setButtonOn(ButtonPunch)
|
||||
}
|
||||
|
||||
if ebiten.IsKeyPressed(ebiten.KeyJ) {
|
||||
in.setButtonOn(ButtonKick)
|
||||
}
|
||||
|
||||
if ebiten.IsKeyPressed(ebiten.KeyK) {
|
||||
in.setButtonOn(ButtonBlock)
|
||||
}
|
||||
|
||||
if ebiten.IsKeyPressed(ebiten.KeyL) {
|
||||
in.setButtonOn(ButtonTaunt)
|
||||
}
|
||||
|
@ -345,6 +353,12 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|||
g.Players[i].VY = g.Players[i].VY * 0.8
|
||||
|
||||
if g.Players[i].Action == component.ActionIdle {
|
||||
if input.isButtonOn(ButtonBlock) {
|
||||
g.Players[i].Action = component.ActionBlock
|
||||
g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionBlock])
|
||||
continue
|
||||
}
|
||||
|
||||
if input.isButtonOn(ButtonTaunt) {
|
||||
var tauntAction component.PlayerAction
|
||||
switch {
|
||||
|
@ -421,16 +435,23 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|||
if frame.T == component.HitboxHurt {
|
||||
// Hit opponent.
|
||||
if oppRect.Overlaps(component.TranslateRect(frameRect, int(player.X), int(player.Y))) {
|
||||
hitStrength := 4.0
|
||||
if g.Players[opp].Action == component.ActionBlock {
|
||||
hitStrength = 1.0
|
||||
}
|
||||
|
||||
// Send the opponent flying in some direction.
|
||||
if opponent.X <= player.X { // Opponent is to the left of the player.
|
||||
opponent.VX = -4
|
||||
opponent.VX = -hitStrength
|
||||
} else { // Opponent is to the right of the player.
|
||||
opponent.VX = 4
|
||||
opponent.VX = hitStrength
|
||||
}
|
||||
|
||||
// Stun the opponent.
|
||||
opponent.Action = component.ActionStunned
|
||||
opponent.ActionTicksLeft = 14
|
||||
if g.Players[opp].Action != component.ActionBlock {
|
||||
opponent.Action = component.ActionStunned
|
||||
opponent.ActionTicksLeft = 14
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -446,6 +467,12 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|||
g.Players[i].ActionTicksLeft--
|
||||
}
|
||||
if g.Players[i].ActionTicksLeft == 0 {
|
||||
// Hold block.
|
||||
if input.isButtonOn(ButtonBlock) {
|
||||
g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionBlock])
|
||||
continue
|
||||
}
|
||||
|
||||
// Return to the idle action.
|
||||
g.Players[i].Action = component.ActionIdle
|
||||
g.Players[i].ActionTicksLeft = len(component.AllPlayerFrames[component.ActionIdle]) // TODO
|
||||
|
@ -480,11 +507,15 @@ func (g *Game) playerStateUpdated() {
|
|||
func (g *Game) RunLocalFrame() {
|
||||
inputs := make([]InputBits, 2)
|
||||
inputs[0] = g.ReadInputs()
|
||||
if world.Mirror || true {
|
||||
inputs[1] = mirrorInput(inputs[0])
|
||||
}
|
||||
g.UpdateByInputs(inputs)
|
||||
|
||||
if world.AI == world.AIMirror {
|
||||
inputs[1] = mirrorInput(inputs[0])
|
||||
} else if world.AI == world.AIBlock {
|
||||
inputs[1] = inputs[0]
|
||||
inputs[1].setButtonOn(ButtonBlock)
|
||||
}
|
||||
|
||||
g.UpdateByInputs(inputs)
|
||||
g.playerStateUpdated()
|
||||
}
|
||||
|
||||
|
@ -544,6 +575,17 @@ func (g *Game) Update() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyI) && ebiten.IsKeyPressed(ebiten.KeyControl) {
|
||||
switch world.AI {
|
||||
case world.AIMirror:
|
||||
world.AI = world.AIBlock
|
||||
case world.AIBlock:
|
||||
world.AI = world.AINone
|
||||
default:
|
||||
world.AI = world.AIMirror
|
||||
}
|
||||
}
|
||||
|
||||
if inpututil.IsKeyJustPressed(ebiten.KeyV) && ebiten.IsKeyPressed(ebiten.KeyControl) {
|
||||
world.Debug++
|
||||
if world.Debug > world.MaxDebug {
|
||||
|
|
|
@ -21,6 +21,8 @@ const (
|
|||
ButtonDown
|
||||
ButtonUp
|
||||
ButtonPunch
|
||||
ButtonKick
|
||||
ButtonBlock
|
||||
ButtonTaunt
|
||||
ButtonStart
|
||||
)
|
||||
|
@ -105,31 +107,15 @@ func encodeInputsGob(inputs Input) []byte {
|
|||
|
||||
func mirrorInput(inputs InputBits) InputBits {
|
||||
left, right := inputs.isButtonOn(ButtonRight), inputs.isButtonOn(ButtonLeft)
|
||||
down, up := inputs.isButtonOn(ButtonUp), inputs.isButtonOn(ButtonDown)
|
||||
|
||||
if left {
|
||||
inputs.setButtonOn(ButtonLeft)
|
||||
} else {
|
||||
inputs.setButtonOff(ButtonLeft)
|
||||
}
|
||||
|
||||
if right {
|
||||
inputs.setButtonOn(ButtonRight)
|
||||
} else {
|
||||
inputs.setButtonOff(ButtonRight)
|
||||
}
|
||||
|
||||
if down {
|
||||
inputs.setButtonOn(ButtonDown)
|
||||
} else {
|
||||
inputs.setButtonOff(ButtonDown)
|
||||
}
|
||||
|
||||
if up {
|
||||
inputs.setButtonOn(ButtonUp)
|
||||
} else {
|
||||
inputs.setButtonOff(ButtonUp)
|
||||
}
|
||||
|
||||
return inputs
|
||||
}
|
||||
|
|
39
system/ui.go
39
system/ui.go
|
@ -38,7 +38,7 @@ type UISystem struct {
|
|||
buffer *etk.Text
|
||||
updateTicks int
|
||||
|
||||
gameOverImg *ebiten.Image
|
||||
tmpImg *ebiten.Image
|
||||
|
||||
hitboxImg *ebiten.Image
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ func (u *UISystem) initialize() {
|
|||
etk.SetRoot(inputDemo)
|
||||
etk.Layout(world.InternalScreenWidth, world.InternalScreenHeight)
|
||||
|
||||
u.gameOverImg = ebiten.NewImage(250, 100)
|
||||
u.tmpImg = ebiten.NewImage(250, 100)
|
||||
|
||||
u.hitboxImg = ebiten.NewImage(32, 32)
|
||||
|
||||
|
@ -250,14 +250,37 @@ func (u *UISystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
|
|||
}
|
||||
}
|
||||
|
||||
if world.Local {
|
||||
u.tmpImg.Clear()
|
||||
|
||||
aiLabel := "NONE"
|
||||
switch world.AI {
|
||||
case world.AIMirror:
|
||||
aiLabel = "MIRROR"
|
||||
case world.AIBlock:
|
||||
aiLabel = "BLOCK"
|
||||
}
|
||||
label := fmt.Sprintf("AI TYPE: %s (CONTROL+I)", aiLabel)
|
||||
ebitenutil.DebugPrint(u.tmpImg, label)
|
||||
|
||||
width := float64(len(label) * 12)
|
||||
height := float64(32)
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Reset()
|
||||
op.GeoM.Scale(2, 2)
|
||||
op.GeoM.Translate(world.InternalScreenWidth/2-width/2, world.InternalScreenHeight-height)
|
||||
screen.DrawImage(u.tmpImg, op)
|
||||
}
|
||||
|
||||
if world.Winner != 0 {
|
||||
u.gameOverImg.Clear()
|
||||
u.tmpImg.Clear()
|
||||
|
||||
label := "YOU LOSE!"
|
||||
if world.Winner == world.CurrentPlayer {
|
||||
label = "YOU WIN!"
|
||||
}
|
||||
ebitenutil.DebugPrint(u.gameOverImg, label)
|
||||
ebitenutil.DebugPrint(u.tmpImg, label)
|
||||
|
||||
width := float64(len(label) * 24)
|
||||
height := float64(64) * 2
|
||||
|
@ -265,9 +288,9 @@ func (u *UISystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
|
|||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Scale(4, 4)
|
||||
op.GeoM.Translate(world.InternalScreenWidth/2-width/2, world.InternalScreenHeight/2-height/2)
|
||||
screen.DrawImage(u.gameOverImg, op)
|
||||
screen.DrawImage(u.tmpImg, op)
|
||||
|
||||
u.gameOverImg.Clear()
|
||||
u.tmpImg.Clear()
|
||||
|
||||
label = "PRESS ENTER OR START TO PLAY AGAIN"
|
||||
p := world.Player1
|
||||
|
@ -277,7 +300,7 @@ func (u *UISystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
|
|||
if p.PlayAgain {
|
||||
label = "WAITING FOR OPPONENT..."
|
||||
}
|
||||
ebitenutil.DebugPrint(u.gameOverImg, label)
|
||||
ebitenutil.DebugPrint(u.tmpImg, label)
|
||||
|
||||
width = float64(len(label) * 12)
|
||||
height = float64(32)
|
||||
|
@ -285,7 +308,7 @@ func (u *UISystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
|
|||
op.GeoM.Reset()
|
||||
op.GeoM.Scale(2, 2)
|
||||
op.GeoM.Translate(world.InternalScreenWidth/2-width/2, world.InternalScreenHeight/2+height/2)
|
||||
screen.DrawImage(u.gameOverImg, op)
|
||||
screen.DrawImage(u.tmpImg, op)
|
||||
}
|
||||
|
||||
if world.Debug != 0 {
|
||||
|
|
|
@ -27,6 +27,14 @@ const (
|
|||
GroundHeight = 100
|
||||
)
|
||||
|
||||
type AIType int
|
||||
|
||||
const (
|
||||
AINone AIType = iota
|
||||
AIMirror
|
||||
AIBlock
|
||||
)
|
||||
|
||||
var (
|
||||
TPS = DefaultTPS
|
||||
|
||||
|
@ -50,8 +58,8 @@ var (
|
|||
|
||||
CurrentPlayer = 1
|
||||
|
||||
Local bool // Playing against computer
|
||||
Mirror bool // AI should mirror player movements
|
||||
Local bool // Playing against computer
|
||||
AI AIType // AI configuration
|
||||
|
||||
Backend ggpo.Backend
|
||||
|
||||
|
|
Loading…
Reference in New Issue