Flip player orientation when they are on the right side
This commit is contained in:
parent
92c1c72668
commit
aad5185f94
|
@ -99,6 +99,17 @@ func FrameDataForActionTick(a PlayerAction, tick int) []FrameData {
|
|||
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
|
||||
|
|
1
flags.go
1
flags.go
|
@ -21,6 +21,7 @@ func parseFlags() {
|
|||
printDebug bool
|
||||
)
|
||||
flag.BoolVar(&fullscreen, "fullscreen", false, "run in fullscreen mode")
|
||||
flag.BoolVar(&world.DisableVsync, "no-vsync", false, "turn off vsync and run at maximum fps")
|
||||
flag.StringVar(&hostAddress, "host", "", "start hosting a match on specified address:port")
|
||||
flag.StringVar(&connectAddress, "connect", "", "connect to a match at specified address:port")
|
||||
flag.IntVar(&world.LocalPort, "local", 0, "set local port (this is not normally required)")
|
||||
|
|
28
game/game.go
28
game/game.go
|
@ -4,6 +4,7 @@ import (
|
|||
"crypto/sha1"
|
||||
"image/color"
|
||||
"log"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -210,7 +211,7 @@ func (g *Game) applyPhysics() {
|
|||
|
||||
// Apply gravity.
|
||||
if p.VY > -world.Gravity {
|
||||
p.VY -= 1
|
||||
p.VY -= math.Max(math.Abs(p.VY/2.5), 0.1)
|
||||
if p.VY < -world.Gravity {
|
||||
p.VY = -world.Gravity
|
||||
}
|
||||
|
@ -240,6 +241,7 @@ func (g *Game) applyPhysics() {
|
|||
|
||||
func (g *Game) UpdateByInputs(inputs []InputBits) {
|
||||
var player, opponent *component.Player
|
||||
var playerFlipped, oppFlipped bool
|
||||
for i, input := range inputs {
|
||||
opp := 0
|
||||
if i == 0 {
|
||||
|
@ -248,6 +250,15 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|||
player = &g.Players[i]
|
||||
opponent = &g.Players[opp]
|
||||
|
||||
if component.PlayerOnRightSide(*player, *opponent) { // Player is on the right side.
|
||||
playerFlipped = true
|
||||
oppFlipped = false
|
||||
} else { // Opponent is on the right side.
|
||||
playerFlipped = false
|
||||
oppFlipped = true
|
||||
}
|
||||
_ = oppFlipped // TODO
|
||||
|
||||
playerRect := world.FloatRect(g.Players[i].X, g.Players[i].Y, g.Players[i].X+float64(component.PlayerSize), g.Players[i].Y+float64(component.PlayerSize))
|
||||
oppRect := world.FloatRect(g.Players[opp].X, g.Players[opp].Y, g.Players[opp].X+float64(component.PlayerSize), g.Players[opp].Y+float64(component.PlayerSize))
|
||||
|
||||
|
@ -256,10 +267,9 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|||
|
||||
if player.Action != component.ActionStunned {
|
||||
if input.isButtonOn(ButtonUp) && !component.TranslateRect(playerRect, 0, -1).Overlaps(oppRect) {
|
||||
grounded := g.Players[i].Y == float64(component.PlayerSize)
|
||||
// TODO check when last jump, grounded
|
||||
grounded := g.Players[i].Y > -world.FloatValueThreshold && g.Players[i].Y < world.FloatValueThreshold
|
||||
if grounded {
|
||||
g.Players[i].VY = 20
|
||||
g.Players[i].VY = world.JumpVelocity
|
||||
}
|
||||
}
|
||||
if input.isButtonOn(ButtonDown) && !component.TranslateRect(playerRect, 0, 1).Overlaps(oppRect) {
|
||||
|
@ -290,10 +300,12 @@ func (g *Game) UpdateByInputs(inputs []InputBits) {
|
|||
|
||||
allFrameData := component.FrameDataForActionTick(g.Players[i].Action, g.Players[i].ActionTicksLeft)
|
||||
for _, frame := range allFrameData {
|
||||
frameRect := component.FlipRect(frame.R, playerFlipped)
|
||||
|
||||
// Apply hitbox.
|
||||
if frame.T == component.HitboxHurt {
|
||||
// Hit opponent.
|
||||
if oppRect.Overlaps(component.TranslateRect(frame.R, int(player.X), int(player.Y))) {
|
||||
if oppRect.Overlaps(component.TranslateRect(frameRect, int(player.X), int(player.Y))) {
|
||||
// Send the opponent flying in some direction.
|
||||
if opponent.X <= player.X { // Opponent is to the left of the player.
|
||||
opponent.VX = -4
|
||||
|
@ -439,7 +451,11 @@ func (g *Game) Update() error {
|
|||
g.RunFrame()
|
||||
}
|
||||
|
||||
return gohan.Update()
|
||||
err := gohan.Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *Game) Draw(screen *ebiten.Image) {
|
||||
|
|
7
main.go
7
main.go
|
@ -16,13 +16,18 @@ func main() {
|
|||
ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled)
|
||||
ebiten.SetWindowSize(world.DefaultScreenWidth, world.DefaultScreenHeight)
|
||||
ebiten.SetWindowClosingHandled(true)
|
||||
ebiten.SetFPSMode(ebiten.FPSModeVsyncOn)
|
||||
ebiten.SetRunnableOnUnfocused(true)
|
||||
|
||||
parseFlags()
|
||||
|
||||
ebiten.SetTPS(world.TPS)
|
||||
|
||||
if world.DisableVsync {
|
||||
ebiten.SetFPSMode(ebiten.FPSModeVsyncOffMaximum)
|
||||
} else {
|
||||
ebiten.SetFPSMode(ebiten.FPSModeVsyncOn)
|
||||
}
|
||||
|
||||
g, err := game.NewGame()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
27
system/ui.go
27
system/ui.go
|
@ -180,17 +180,17 @@ func (u *UISystem) Update(e gohan.Entity) error {
|
|||
return etk.Update()
|
||||
}
|
||||
|
||||
func (u *UISystem) drawBox(screen *ebiten.Image, fillColor color.Color, x float64, y float64, w int, h int) {
|
||||
func (u *UISystem) drawBox(screen *ebiten.Image, fillColor color.Color, r image.Rectangle) {
|
||||
bounds := u.hitboxImg.Bounds()
|
||||
if bounds.Dx() != w || bounds.Dy() != h {
|
||||
u.hitboxImg = ebiten.NewImage(w, h)
|
||||
if bounds.Dx() != r.Dx() || bounds.Dy() != r.Dy() {
|
||||
u.hitboxImg = ebiten.NewImage(r.Dx(), r.Dy())
|
||||
}
|
||||
u.hitboxImg.Clear()
|
||||
u.hitboxImg.Fill(color.RGBA{255, 255, 255, 255})
|
||||
u.hitboxImg.SubImage(image.Rect(2, 2, w-2, h-2)).(*ebiten.Image).Fill(fillColor)
|
||||
u.hitboxImg.SubImage(image.Rect(2, 2, r.Dx()-2, r.Dy()-2)).(*ebiten.Image).Fill(fillColor)
|
||||
|
||||
// Get screen position of top left corner of player.
|
||||
drawX, drawY := world.GameCoordsToScreen(x, y)
|
||||
drawX, drawY := world.GameCoordsToScreen(float64(r.Min.X), float64(r.Min.Y+r.Dy()))
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Translate(float64(drawX), float64(drawY))
|
||||
|
@ -209,31 +209,38 @@ func (u *UISystem) Draw(e gohan.Entity, screen *ebiten.Image) error {
|
|||
return err
|
||||
}
|
||||
} else if world.Debug > 1 { // In-game and debug mode is enabled
|
||||
var p *component.Player
|
||||
var p, o *component.Player
|
||||
for i := 0; i < 2; i++ {
|
||||
if i == 0 {
|
||||
p = &world.Player1
|
||||
o = &world.Player2
|
||||
} else {
|
||||
p = &world.Player2
|
||||
o = &world.Player1
|
||||
}
|
||||
|
||||
if p.ActionTicksLeft != 0 {
|
||||
// Draw a rect over stunned players.
|
||||
if p.Action == component.ActionStunned {
|
||||
playerRect := world.FloatRect(p.X, p.Y, p.X+float64(component.PlayerSize), p.Y+float64(component.PlayerSize))
|
||||
|
||||
fillColor := color.RGBA{123, 30, 255, 255}
|
||||
u.drawBox(screen, fillColor, p.X, p.Y+component.PlayerSize, component.PlayerSize, component.PlayerSize)
|
||||
u.drawBox(screen, fillColor, playerRect)
|
||||
continue
|
||||
}
|
||||
|
||||
// Draw frame data rects.
|
||||
allData := component.FrameDataForActionTick(p.Action, p.ActionTicksLeft)
|
||||
for _, data := range allData {
|
||||
for _, frame := range allData {
|
||||
frameRect := component.FlipRect(frame.R, component.PlayerOnRightSide(*p, *o))
|
||||
frameRect = component.TranslateRect(frameRect, int(p.X), int(p.Y))
|
||||
|
||||
fillColor := color.RGBA{0, 255, 0, 255}
|
||||
switch data.T {
|
||||
switch frame.T {
|
||||
case component.HitboxHurt:
|
||||
fillColor = color.RGBA{0, 0, 255, 255}
|
||||
}
|
||||
u.drawBox(screen, fillColor, p.X, p.Y+float64(data.R.Dy()), data.R.Dx(), data.R.Dy())
|
||||
u.drawBox(screen, fillColor, frameRect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,16 +15,22 @@ const (
|
|||
|
||||
InternalScreenWidth, InternalScreenHeight = 854, 480
|
||||
|
||||
Gravity = 6.0
|
||||
Gravity = 3
|
||||
|
||||
GroundHeight = 100 // TODO
|
||||
JumpVelocity = 30
|
||||
|
||||
GroundHeight = 100
|
||||
|
||||
MaxDebug = 2
|
||||
|
||||
FloatValueThreshold = 0.00000001
|
||||
)
|
||||
|
||||
var (
|
||||
TPS = DefaultTPS
|
||||
|
||||
DisableVsync bool
|
||||
|
||||
ScreenWidth, ScreenHeight = 0, 0
|
||||
|
||||
CamX, CamY = 0, 0 // TODO currently static
|
||||
|
|
Loading…
Reference in New Issue