Finished project. Enemies, PvP, Music, menug
This commit is contained in:
parent
461d177cfa
commit
c3de6b0a9a
|
@ -0,0 +1,8 @@
|
|||
package main
|
||||
|
||||
type Actor interface {
|
||||
Update() bool
|
||||
Draw()
|
||||
TakeHit(Actor)
|
||||
GetPosition() Vector
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package main
|
||||
|
||||
import "cart/w4"
|
||||
|
||||
type Bullet struct {
|
||||
Position Vector
|
||||
SpeedX int8
|
||||
SpeedY int8
|
||||
Owner Actor
|
||||
Dead bool
|
||||
}
|
||||
|
||||
func (b *Bullet) GetPosition() Vector {
|
||||
return b.Position
|
||||
}
|
||||
|
||||
func (b *Bullet) Update() bool {
|
||||
if b.Dead {
|
||||
return true
|
||||
}
|
||||
b.Position.Move(float64(b.SpeedX), float64(b.SpeedY))
|
||||
if b.Position.X < 0 || b.Position.X > 320 || b.Position.Y < -160 || b.Position.Y > 320 {
|
||||
return true
|
||||
}
|
||||
for _, actor := range actors {
|
||||
if actor == Actor(b.Owner) || actor == b {
|
||||
continue
|
||||
}
|
||||
if _, ok := actor.(*Bullet); ok {
|
||||
continue
|
||||
}
|
||||
diff := b.Position.Sub(actor.GetPosition())
|
||||
if diff.LenSquared() < 60 {
|
||||
actor.TakeHit(b)
|
||||
// b.TakeHit(b)
|
||||
b.Dead = true
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *Bullet) Draw() {
|
||||
*w4.DRAW_COLORS = 0x41
|
||||
w4.Oval(int(b.Position.X)-3-camX, int(b.Position.Y)-3-camY, 6, 6)
|
||||
}
|
||||
|
||||
func (b *Bullet) TakeHit(from Actor) {
|
||||
w4.Tone(800, 10<<8, 20, w4.TONE_MODE2)
|
||||
b.Dead = true
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"cart/w4"
|
||||
"math"
|
||||
)
|
||||
|
||||
const enemyWidth = 8
|
||||
const enemyHeight = 8
|
||||
const enemyFlags = 1 // BLIT_2BPP
|
||||
var enemy = [16]byte{0x80, 0x80, 0xaa, 0x80, 0xa6, 0xa4, 0xa9, 0x9a, 0xaa, 0xaa, 0xaa, 0x9a, 0xaa, 0xa8, 0x20, 0x20}
|
||||
|
||||
type Enemy struct {
|
||||
Position Vector
|
||||
Speed Vector
|
||||
Dead bool
|
||||
ShootTimer uint8
|
||||
}
|
||||
|
||||
func (e *Enemy) GetPosition() Vector {
|
||||
return e.Position
|
||||
}
|
||||
|
||||
func (e *Enemy) Update() bool {
|
||||
if e.Position.Y > 320 {
|
||||
return true
|
||||
}
|
||||
if e.Dead {
|
||||
e.Speed.Y = math.Min(e.Speed.Y+0.2, 4)
|
||||
}
|
||||
e.Position.MoveVec(e.Speed)
|
||||
if e.Position.X < 0 && e.Speed.X < 0 {
|
||||
e.Position.X = 0
|
||||
e.Speed.X *= -1
|
||||
}
|
||||
if e.Position.X > 320 && e.Speed.X > 0 {
|
||||
e.Position.X = 320
|
||||
e.Speed.X *= -1
|
||||
}
|
||||
if e.ShootTimer > 0 {
|
||||
e.ShootTimer--
|
||||
} else if e.Position.X > 0 && e.Position.X < 320 {
|
||||
e.ShootTimer = 180
|
||||
distance := math.MaxFloat64
|
||||
direction := Vector{}
|
||||
var player *Player
|
||||
for _, p := range players {
|
||||
if p.Health == 0 {
|
||||
continue
|
||||
}
|
||||
diff := p.Position.Sub(e.Position)
|
||||
dis := diff.LenSquared()
|
||||
if distance > dis {
|
||||
distance = dis
|
||||
player = p
|
||||
direction = diff.Normalized()
|
||||
}
|
||||
|
||||
}
|
||||
if player != nil {
|
||||
sx := int8(direction.X*5) / 3
|
||||
sy := int8(direction.Y*5) / 3
|
||||
b := &Bullet{
|
||||
Position: e.Position,
|
||||
Owner: e,
|
||||
SpeedX: sx,
|
||||
SpeedY: sy,
|
||||
}
|
||||
w4.Tone(400|300<<16, 3, 5, w4.TONE_PULSE2)
|
||||
actors = append(actors, b)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Enemy) Draw() {
|
||||
*w4.DRAW_COLORS = 0x44
|
||||
var f uint = w4.BLIT_2BPP
|
||||
if e.Speed.X < 0 {
|
||||
f |= w4.BLIT_FLIP_X
|
||||
}
|
||||
*w4.DRAW_COLORS = 0x430
|
||||
w4.Blit(&enemy[0], int(e.Position.X)-camX-4, int(e.Position.Y)-camY-4, 8, 8, f)
|
||||
}
|
||||
|
||||
func (e *Enemy) TakeHit(from Actor) {
|
||||
if e.Dead {
|
||||
return
|
||||
}
|
||||
if bullet, ok := from.(*Bullet); ok {
|
||||
if _, ok := bullet.Owner.(*Player); !ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
enemies--
|
||||
kills++
|
||||
e.Dead = true
|
||||
e.Speed.Y = -3
|
||||
w4.Tone(300|200<<16, 5, 20, w4.TONE_PULSE2)
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"cart/w4"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var gravity = 0.2
|
||||
var points []*Point = []*Point{}
|
||||
var sticks []*Stick = []*Stick{}
|
||||
var actors []Actor = []Actor{}
|
||||
var enemies uint = 0
|
||||
var players []*Player
|
||||
var playersAlive = 0
|
||||
var kills int = 0
|
||||
var lightIndex uint64 = 0
|
||||
var camX int = 0
|
||||
var camY int = 0
|
||||
var deathTimer = 180
|
||||
var music *Music
|
||||
|
||||
func gameStart() {
|
||||
kills = 0
|
||||
deathTimer = 180
|
||||
rand.Seed(int64(frame))
|
||||
music = &Music{
|
||||
KickProb: [8]uint8{100, 10, 25, 15, 50, 10, 20, 30},
|
||||
SnareProb: [8]uint8{0, 0, 70, 20, 20, 10, 70, 30},
|
||||
LeadProb: [8]uint8{90, 70, 60, 60, 90, 60, 70, 60},
|
||||
MainNoteIndex: 1,
|
||||
}
|
||||
if musicEnabled {
|
||||
music.Start()
|
||||
}
|
||||
points = []*Point{}
|
||||
sticks = []*Stick{}
|
||||
actors = []Actor{}
|
||||
players = []*Player{}
|
||||
|
||||
for i := 0.0; i < 8; i++ {
|
||||
var y1, y2 float64
|
||||
if int(i)%2 == 0 {
|
||||
y1 = rand.Float64()*40 - 20
|
||||
y2 = rand.Float64() * 40
|
||||
} else {
|
||||
y1 = rand.Float64() * 40
|
||||
y2 = rand.Float64()*40 - 20
|
||||
}
|
||||
|
||||
p, s := CreateRope(
|
||||
Vector{0, y1 + i*30},
|
||||
Vector{320, y2 + i*30},
|
||||
14,
|
||||
)
|
||||
points = append(points, p...)
|
||||
sticks = append(sticks, s...)
|
||||
}
|
||||
playersAlive = playersCount
|
||||
for i, ready := range readyPlayers {
|
||||
if !ready {
|
||||
continue
|
||||
}
|
||||
player := &Player{
|
||||
Index: uint8(i),
|
||||
Health: 20,
|
||||
ShootTimer: 10,
|
||||
Position: Vector{80, 80},
|
||||
Speed: Vector{},
|
||||
Gamepad: gamepads[i],
|
||||
StickGrabbed: sticks[rand.Intn(len(sticks)-1)],
|
||||
}
|
||||
actors = append(actors, player)
|
||||
players = append(players, player)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func gameUpdate() {
|
||||
if (!pvp && playersAlive == 0) || (pvp && playersAlive <= 1) {
|
||||
if deathTimer--; deathTimer == 0 {
|
||||
if !pvp && kills > maxKills {
|
||||
w4.DiskW(unsafe.Pointer(&kills), 4)
|
||||
}
|
||||
menuStart()
|
||||
stateUpdate = menuUpdate
|
||||
}
|
||||
}
|
||||
music.Update()
|
||||
frame += 1
|
||||
Simulate(points, sticks)
|
||||
if frame%120 == 0 && enemies < 10 && !pvp {
|
||||
spX := rand.Float64()*2 - 1
|
||||
posY := rand.Float64()*200 + 50
|
||||
posX := float64(-160)
|
||||
if spX < 0 {
|
||||
posX = 480
|
||||
}
|
||||
|
||||
e := &Enemy{
|
||||
Position: Vector{posX, posY},
|
||||
Speed: Vector{spX, 0},
|
||||
ShootTimer: uint8(rand.Uint32() % 120),
|
||||
}
|
||||
enemies++
|
||||
actors = append(actors, e)
|
||||
}
|
||||
actorsToRemove := []int{}
|
||||
for i, actor := range actors {
|
||||
if actor.Update() {
|
||||
actorsToRemove = append(actorsToRemove, i)
|
||||
}
|
||||
}
|
||||
for i := len(actorsToRemove) - 1; i > 0; i-- {
|
||||
actor := actorsToRemove[i]
|
||||
actors = append(actors[:actor], actors[actor+1:]...)
|
||||
}
|
||||
target := players[0]
|
||||
isDead := false
|
||||
if *w4.NETPLAY&0b100 != 0 {
|
||||
playerId := *w4.NETPLAY & 0b11
|
||||
target = players[playerId]
|
||||
if target.Health == 0 {
|
||||
isDead = true
|
||||
if plr, ok := target.KilledBy.(*Player); ok {
|
||||
target = plr
|
||||
}
|
||||
}
|
||||
}
|
||||
camX, camY = int(target.Position.X)-80, int(target.Position.Y)-80
|
||||
for _, s := range sticks {
|
||||
s.Draw()
|
||||
}
|
||||
for _, p := range points {
|
||||
p.Draw()
|
||||
}
|
||||
for _, actor := range actors {
|
||||
actor.Draw()
|
||||
}
|
||||
|
||||
*w4.DRAW_COLORS = 0x23
|
||||
w4.Rect(-160-camX, -100-camY, 160, 500)
|
||||
w4.Rect(320-camX, -100-camY, 160, 500)
|
||||
*w4.DRAW_COLORS = 0x4
|
||||
if !pvp {
|
||||
w4.Text(strconv.Itoa(kills)+" kills", 1, 1)
|
||||
}
|
||||
// w4.Text(strconv.Itoa(playersAlive), 0, 0)
|
||||
if !isDead {
|
||||
if !pvp || (pvp && playersAlive > 1) {
|
||||
w4.Text("health", 57, 151)
|
||||
hbar := float32(target.Health) / 20 * 80
|
||||
w4.Rect(int(80-hbar), 150, uint(hbar*2), 10)
|
||||
*w4.DRAW_COLORS = 0x1
|
||||
w4.Text("health", 57, 151)
|
||||
} else {
|
||||
w4.Text("winner", 57, 151)
|
||||
}
|
||||
} else {
|
||||
w4.Text(" dead ", 57, 151)
|
||||
}
|
||||
}
|
63
main.go
63
main.go
|
@ -1,74 +1,23 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"cart/w4"
|
||||
"math/rand"
|
||||
)
|
||||
import "cart/w4"
|
||||
|
||||
var gravity = 0.2
|
||||
var points []*Point = []*Point{}
|
||||
var sticks []*Stick = []*Stick{}
|
||||
var player *Player
|
||||
var frame uint64 = 0
|
||||
var lightIndex uint64 = 0
|
||||
var camX int = 0
|
||||
var camY int = 0
|
||||
var stateUpdate func()
|
||||
|
||||
//go:export start
|
||||
func start() {
|
||||
|
||||
rand.Seed(654348654)
|
||||
points = []*Point{}
|
||||
sticks = []*Stick{}
|
||||
frame = 0
|
||||
w4.PALETTE[0] = 0xfcdeea
|
||||
w4.PALETTE[1] = 0x012824
|
||||
w4.PALETTE[2] = 0x265935
|
||||
w4.PALETTE[3] = 0xff4d6d
|
||||
|
||||
for i := 0.0; i < 8; i++ {
|
||||
var y1, y2 float64
|
||||
if int(i)%2 == 0 {
|
||||
y1 = rand.Float64()*40 - 20
|
||||
y2 = rand.Float64() * 40
|
||||
} else {
|
||||
y1 = rand.Float64() * 40
|
||||
y2 = rand.Float64()*40 - 20
|
||||
}
|
||||
|
||||
p, s := CreateRope(
|
||||
Vector{0, y1 + i*30},
|
||||
Vector{320, y2 + i*30},
|
||||
14,
|
||||
)
|
||||
points = append(points, p...)
|
||||
sticks = append(sticks, s...)
|
||||
}
|
||||
|
||||
player = &Player{
|
||||
Position: Vector{80, 80},
|
||||
Speed: Vector{},
|
||||
Gamepad: w4.GAMEPAD1,
|
||||
StickGrabbed: sticks[rand.Intn(len(sticks)-1)],
|
||||
}
|
||||
menuStart()
|
||||
}
|
||||
|
||||
//go:export update
|
||||
func update() {
|
||||
frame += 1
|
||||
*w4.DRAW_COLORS = 2
|
||||
// w4.Text("Hello from Go!", 10, 10)
|
||||
Simulate(points, sticks)
|
||||
player.Update()
|
||||
camX, camY = int(player.Position.X)-80, int(player.Position.Y)-80
|
||||
for _, s := range sticks {
|
||||
s.Draw()
|
||||
}
|
||||
for _, p := range points {
|
||||
p.Draw()
|
||||
}
|
||||
player.Draw()
|
||||
|
||||
*w4.DRAW_COLORS = 0x23
|
||||
w4.Rect(-160-camX, -100-camY, 160, 500)
|
||||
w4.Rect(320-camX, -100-camY, 160, 500)
|
||||
frame++
|
||||
stateUpdate()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"cart/w4"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
var readyPlayers = [4]bool{false, false, false, false}
|
||||
var pvp = false
|
||||
var playersCount = 0
|
||||
var maxKills int = 0
|
||||
var gamepads = []*uint8{
|
||||
w4.GAMEPAD1,
|
||||
w4.GAMEPAD2,
|
||||
w4.GAMEPAD3,
|
||||
w4.GAMEPAD4,
|
||||
}
|
||||
|
||||
var options = []string{"Survival (1P)", "PvP (Netplay only)", "Music: ON"}
|
||||
var selected = 0
|
||||
var musicEnabled = true
|
||||
var lastGamepad uint8
|
||||
|
||||
func menuStart() {
|
||||
w4.DiskR(unsafe.Pointer(&maxKills), 4)
|
||||
playersCount = 0
|
||||
readyPlayers = [4]bool{false, false, false, false}
|
||||
stateUpdate = menuUpdate
|
||||
selected = 0
|
||||
}
|
||||
|
||||
func menuUpdate() {
|
||||
frame++
|
||||
gpPressed := *w4.GAMEPAD1 & (*w4.GAMEPAD1 ^ lastGamepad)
|
||||
lastGamepad = *w4.GAMEPAD1
|
||||
if gpPressed&w4.BUTTON_DOWN != 0 {
|
||||
selected = (selected + 1) % len(options)
|
||||
}
|
||||
if gpPressed&w4.BUTTON_UP != 0 {
|
||||
selected = (selected - 1) % len(options)
|
||||
}
|
||||
if gpPressed&w4.BUTTON_1 != 0 {
|
||||
switch selected {
|
||||
case 0:
|
||||
readyPlayers = [4]bool{true, false, false, false}
|
||||
playersCount = 1
|
||||
pvp = false
|
||||
gameStart()
|
||||
stateUpdate = gameUpdate
|
||||
case 1:
|
||||
if playersCount > 1 {
|
||||
pvp = true
|
||||
gameStart()
|
||||
stateUpdate = gameUpdate
|
||||
}
|
||||
case 2:
|
||||
musicEnabled = !musicEnabled
|
||||
if musicEnabled {
|
||||
options[2] = "Music: ON"
|
||||
} else {
|
||||
options[2] = "Music: OFF"
|
||||
}
|
||||
}
|
||||
}
|
||||
for i, gp := range gamepads {
|
||||
if *gp&w4.BUTTON_2 != 0 {
|
||||
if !readyPlayers[i] {
|
||||
readyPlayers[i] = true
|
||||
playersCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
w4.Text(strconv.Itoa(maxKills)+" kills", 2, 40)
|
||||
w4.Text("CHRISTMAS\nLIGHTS\nMASSACRE", 70, 2)
|
||||
w4.Text("Press Z to get ready", 0, 150)
|
||||
for i, opt := range options {
|
||||
*w4.DRAW_COLORS = 0x3
|
||||
if i == selected {
|
||||
*w4.DRAW_COLORS = 0x4
|
||||
}
|
||||
w4.Text(opt, 2, 60+i*9)
|
||||
*w4.DRAW_COLORS = 0x2
|
||||
}
|
||||
for i, v := range readyPlayers {
|
||||
if v {
|
||||
w4.Text("Player "+strconv.Itoa(i+1)+" is ready", 8, 100+i*8)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"cart/w4"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
const (
|
||||
C int = iota
|
||||
Cs
|
||||
D
|
||||
Ds
|
||||
E
|
||||
F
|
||||
Fs
|
||||
G
|
||||
Gs
|
||||
A
|
||||
As
|
||||
B
|
||||
)
|
||||
|
||||
var frequencies = []uint{262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494}
|
||||
|
||||
type Music struct {
|
||||
KickProb [8]uint8
|
||||
KickLine [8]bool
|
||||
SnareProb [8]uint8
|
||||
SnareLine [8]bool
|
||||
LeadProb [8]uint8
|
||||
LeadLine [8]uint
|
||||
MainNoteIndex int
|
||||
Frame uint64
|
||||
CurrentPart uint8
|
||||
CurrentLine uint8
|
||||
Active bool
|
||||
MutedFrames uint
|
||||
}
|
||||
|
||||
func (m *Music) Start() {
|
||||
m.GenLines()
|
||||
m.Frame = 0
|
||||
m.CurrentLine = 0
|
||||
m.CurrentPart = 0
|
||||
m.Active = true
|
||||
}
|
||||
func (m *Music) Pause() {
|
||||
m.Active = false
|
||||
}
|
||||
func (m *Music) Resume() {
|
||||
m.Active = true
|
||||
m.MutedFrames = 0
|
||||
}
|
||||
|
||||
func (m *Music) MuteFor(frames uint) {
|
||||
m.MutedFrames = frames
|
||||
}
|
||||
|
||||
var pentaScale = []int{0, 3, 5, 7, 10, 12}
|
||||
|
||||
func (m *Music) PentaNote(n int) uint {
|
||||
pentaIndex := n % 6
|
||||
octave := 1 + n/6
|
||||
// w4.Trace("Octave: " + strconv.Itoa(octave))
|
||||
noteIndex := (m.MainNoteIndex + pentaScale[pentaIndex]) % 12
|
||||
return frequencies[noteIndex] * uint(octave)
|
||||
}
|
||||
|
||||
func (m *Music) Update() {
|
||||
if !m.Active {
|
||||
return
|
||||
}
|
||||
if m.MutedFrames > 0 {
|
||||
m.MutedFrames--
|
||||
}
|
||||
if m.Frame%15 == 0 {
|
||||
if m.MutedFrames == 0 {
|
||||
if m.KickLine[m.CurrentLine] {
|
||||
w4.Tone(200|1<<16, 5, 60, w4.TONE_TRIANGLE)
|
||||
}
|
||||
if m.SnareLine[m.CurrentLine] {
|
||||
w4.Tone(200|50<<16, 10<<8, 10, w4.TONE_NOISE)
|
||||
}
|
||||
if m.LeadLine[m.CurrentLine] != 0 {
|
||||
w4.Tone(m.LeadLine[m.CurrentLine], 10|15<<8, 5, w4.TONE_MODE2|w4.TONE_PULSE2)
|
||||
}
|
||||
}
|
||||
m.CurrentLine++
|
||||
if m.CurrentLine == 8 {
|
||||
m.CurrentLine = 0
|
||||
m.CurrentPart++
|
||||
if m.CurrentPart == 4 {
|
||||
m.CurrentPart = 0
|
||||
m.GenLines()
|
||||
}
|
||||
}
|
||||
}
|
||||
m.Frame++
|
||||
}
|
||||
|
||||
func (m *Music) GenLines() {
|
||||
m.KickLine = m.GenDrumLine(m.KickProb)
|
||||
m.SnareLine = m.GenDrumLine(m.SnareProb)
|
||||
m.LeadLine = m.GenLeadLine(m.LeadProb)
|
||||
m.MainNoteIndex = rand.Intn(5)
|
||||
}
|
||||
|
||||
func (m *Music) GenDrumLine(prob [8]uint8) [8]bool {
|
||||
line := [8]bool{}
|
||||
for i, p := range prob {
|
||||
line[i] = rand.Intn(101) < int(p)
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
func (m *Music) GenLeadLine(prob [8]uint8) [8]uint {
|
||||
line := [8]uint{}
|
||||
pattern := [8]int{}
|
||||
offset := rand.Intn(6)
|
||||
switch rand.Intn(4) {
|
||||
case 0:
|
||||
pattern = [8]int{0, 1, 2, 3, 0, 1, 2, 3}
|
||||
case 1:
|
||||
pattern = [8]int{3, 2, 1, 0, 3, 2, 1, 0}
|
||||
case 2:
|
||||
pattern = [8]int{7, 5, 6, 4, 5, 3, 4, 2}
|
||||
case 3:
|
||||
pattern = [8]int{0, 2, 1, 3, 2, 4, 3, 5}
|
||||
case 4:
|
||||
pattern = [8]int{0, 2, 4, 1, 3, 5, 2, 4}
|
||||
case 5:
|
||||
pattern = [8]int{4, 2, 5, 3, 1, 4, 2, 0}
|
||||
}
|
||||
for i, p := range prob {
|
||||
if rand.Intn(101) < int(p) {
|
||||
line[i] = m.PentaNote(pattern[i]+offset) / 2
|
||||
continue
|
||||
}
|
||||
line[i] = 0
|
||||
}
|
||||
return line
|
||||
}
|
118
player.go
118
player.go
|
@ -7,39 +7,64 @@ import (
|
|||
)
|
||||
|
||||
type Player struct {
|
||||
Position Vector
|
||||
Speed Vector
|
||||
//PointGrabbed *Point
|
||||
Index uint8
|
||||
Health uint8
|
||||
KilledBy Actor
|
||||
Position Vector
|
||||
Speed Vector
|
||||
StickGrabbed *Stick
|
||||
StickOffset float64
|
||||
GrabTimeout uint
|
||||
GrabTimer uint8
|
||||
ShootTimer uint8
|
||||
ShootDirX int8
|
||||
ShootDirY int8
|
||||
Gamepad *uint8
|
||||
GamepadLast uint8
|
||||
}
|
||||
|
||||
func (p *Player) Update() {
|
||||
func (p *Player) GetPosition() Vector {
|
||||
return p.Position
|
||||
}
|
||||
|
||||
func (p *Player) Update() bool {
|
||||
var dirX int8 = int8(*p.Gamepad&w4.BUTTON_RIGHT>>5) - int8(*p.Gamepad&w4.BUTTON_LEFT>>4)
|
||||
var dirY int8 = int8(*p.Gamepad&w4.BUTTON_DOWN>>7) - int8(*p.Gamepad&w4.BUTTON_UP>>6)
|
||||
if !(dirX == 0 && dirY == 0) && p.Health > 0 {
|
||||
p.ShootDirX = dirX
|
||||
p.ShootDirY = dirY
|
||||
}
|
||||
lastGamepad := *p.Gamepad & (*p.Gamepad ^ p.GamepadLast)
|
||||
p.GamepadLast = *p.Gamepad
|
||||
if p.GrabTimeout > 0 {
|
||||
p.GrabTimeout--
|
||||
if p.GrabTimer > 0 {
|
||||
p.GrabTimer--
|
||||
}
|
||||
if p.ShootTimer > 0 {
|
||||
p.ShootTimer--
|
||||
} else {
|
||||
if *p.Gamepad&w4.BUTTON_1 != 0 && !(p.ShootDirX == 0 && p.ShootDirY == 0) {
|
||||
bullet := &Bullet{
|
||||
Owner: p,
|
||||
Position: p.Position,
|
||||
SpeedX: p.ShootDirX * 3,
|
||||
SpeedY: p.ShootDirY * 3,
|
||||
}
|
||||
// w4.Trace(strconv.Itoa(int(p.ShootDirX)))
|
||||
// w4.Trace(strconv.Itoa(int(p.ShootDirY)))
|
||||
// w4.Trace(p.Position.String())
|
||||
w4.Tone(150|50<<16, 10, 100, w4.TONE_MODE1)
|
||||
p.ShootTimer = 15
|
||||
actors = append(actors, bullet)
|
||||
}
|
||||
}
|
||||
|
||||
isJumping := *p.Gamepad&w4.BUTTON_DOWN == 0
|
||||
p.Speed.Y = math.Min(4, p.Speed.Y+gravity)
|
||||
if p.StickGrabbed != nil {
|
||||
p.Speed.Y = 0
|
||||
p.Speed.X = 0
|
||||
// p.Position = p.PointGrabbed.Position
|
||||
if *p.Gamepad&w4.BUTTON_LEFT != 0 {
|
||||
p.Speed.X -= 1
|
||||
}
|
||||
if *p.Gamepad&w4.BUTTON_RIGHT != 0 {
|
||||
p.Speed.X += 1
|
||||
}
|
||||
if *p.Gamepad&w4.BUTTON_UP != 0 {
|
||||
p.Speed.Y -= 1
|
||||
}
|
||||
if *p.Gamepad&w4.BUTTON_DOWN != 0 {
|
||||
p.Speed.Y += 1
|
||||
p.Speed.Y = 0
|
||||
if *p.Gamepad&w4.BUTTON_1 == 0 {
|
||||
p.Speed.X = float64(dirX)
|
||||
p.Speed.Y = float64(dirY)
|
||||
}
|
||||
p.MoveOnRope(p.Speed)
|
||||
if p.StickOffset < 0 {
|
||||
|
@ -62,9 +87,9 @@ func (p *Player) Update() {
|
|||
}
|
||||
p.Position = p.StickGrabbed.GetPosition(p.StickOffset)
|
||||
if lastGamepad&w4.BUTTON_2 != 0 {
|
||||
p.GrabTimeout = 10
|
||||
p.GrabTimer = 10
|
||||
if isJumping {
|
||||
p.GrabTimeout = 10
|
||||
p.GrabTimer = 10
|
||||
p.Speed = p.Speed.MulScalar(2)
|
||||
if p.Speed.Y <= 0 {
|
||||
p.Speed.Y -= 1 * 2
|
||||
|
@ -75,9 +100,17 @@ func (p *Player) Update() {
|
|||
}
|
||||
p.StickGrabbed = nil
|
||||
}
|
||||
if p.ShootTimer == 15 {
|
||||
impulse := Vector{-float64(dirX), -float64(dirY)}
|
||||
if p.StickGrabbed != nil {
|
||||
p.StickGrabbed.PointA.Position.MoveVec(impulse)
|
||||
p.StickGrabbed.PointB.Position.MoveVec(impulse)
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
p.Position.Move(p.Speed.X, p.Speed.Y)
|
||||
if *p.Gamepad&w4.BUTTON_DOWN == 0 && p.GrabTimeout == 0 {
|
||||
if *p.Gamepad&w4.BUTTON_DOWN == 0 && p.GrabTimer == 0 && p.Health > 0 {
|
||||
distance := math.MaxFloat64
|
||||
var selectedPoint *Point
|
||||
for _, point := range points {
|
||||
|
@ -98,7 +131,6 @@ func (p *Player) Update() {
|
|||
}
|
||||
}
|
||||
if stickDistance < 4 {
|
||||
w4.Trace(strconv.FormatFloat(stickDistance, 'f', 3, 64))
|
||||
p.StickGrabbed = selectedStick
|
||||
p.StickOffset = selectedStick.GetOffset(p.Position)
|
||||
p.StickGrabbed.PointA.Position.MoveVec(p.Speed)
|
||||
|
@ -107,6 +139,11 @@ func (p *Player) Update() {
|
|||
}
|
||||
}
|
||||
p.Position.X = math.Min(math.Max(0, p.Position.X), 320)
|
||||
if p.Position.Y > 320 && p.Health > 0 {
|
||||
p.Health = 0
|
||||
p.Death()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *Player) MoveOnRope(motion Vector) {
|
||||
|
@ -117,5 +154,36 @@ func (p *Player) MoveOnRope(motion Vector) {
|
|||
|
||||
func (p *Player) Draw() {
|
||||
*w4.DRAW_COLORS = 0x34
|
||||
w4.Rect(int(p.Position.X)-4-camX, int(p.Position.Y)-4-camY, 8, 8)
|
||||
drawX := int(p.Position.X) - 4 - camX
|
||||
drawY := int(p.Position.Y) - 4 - camY
|
||||
w4.Rect(drawX, drawY, 8, 8)
|
||||
|
||||
eyePosX := drawX + 4 + int(p.ShootDirX)
|
||||
eyePosY := drawY + 4 - 2 + int(p.ShootDirY)
|
||||
w4.Rect(eyePosX-2, eyePosY, 1, 2)
|
||||
w4.Rect(eyePosX+1, eyePosY, 1, 2)
|
||||
if pvp {
|
||||
*w4.DRAW_COLORS = 0x4
|
||||
w4.Text("P"+strconv.Itoa(int(p.Index+1)), drawX-3, drawY-10)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) TakeHit(from Actor) {
|
||||
if p.Health > 0 {
|
||||
if p.Health--; p.Health == 0 {
|
||||
if bullet, ok := from.(*Bullet); ok {
|
||||
p.StickGrabbed = nil
|
||||
p.KilledBy = bullet.Owner
|
||||
p.Death()
|
||||
}
|
||||
}
|
||||
w4.Tone(250|200<<16, 15, 60, w4.TONE_PULSE1)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Player) Death() {
|
||||
p.Speed.Y = -3
|
||||
playersAlive--
|
||||
music.MuteFor(30)
|
||||
w4.Tone(600|200<<16, 15|15<<8, 30, w4.TONE_PULSE2)
|
||||
}
|
||||
|
|
13
ropes.go
13
ropes.go
|
@ -9,7 +9,7 @@ type Point struct {
|
|||
Position Vector
|
||||
PreviousPosition Vector
|
||||
IsLocked bool
|
||||
TimeOffset uint64
|
||||
TimeOffset uint16
|
||||
Sticks []*Stick
|
||||
}
|
||||
|
||||
|
@ -24,14 +24,15 @@ func (p *Point) GetMotion() Vector {
|
|||
|
||||
func (p *Point) Draw() {
|
||||
*w4.DRAW_COLORS = 0x31
|
||||
fr := (frame + p.TimeOffset) % 60
|
||||
fr := (frame + uint64(p.TimeOffset)) % 60
|
||||
if fr > 20 {
|
||||
*w4.DRAW_COLORS = 0x32
|
||||
}
|
||||
if fr > 40 {
|
||||
*w4.DRAW_COLORS = 0x34
|
||||
}
|
||||
if fr > 40 {
|
||||
*w4.DRAW_COLORS = 0x32
|
||||
}
|
||||
w4.Oval(int(p.Position.X)-2-camX, int(p.Position.Y)-2-camY, 4, 4)
|
||||
|
||||
}
|
||||
|
||||
type Stick struct {
|
||||
|
@ -129,7 +130,7 @@ func CreateRope(start Vector, end Vector, divisions int) ([]*Point, []*Stick) {
|
|||
Position: pos,
|
||||
PreviousPosition: pos,
|
||||
IsLocked: (i == 0 || i == divisions),
|
||||
TimeOffset: lightIndex * 153,
|
||||
TimeOffset: uint16(lightIndex * 147),
|
||||
}
|
||||
lightIndex++
|
||||
if i != 0 {
|
||||
|
|
Loading…
Reference in New Issue