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
|
package main
|
||||||
|
|
||||||
import (
|
import "cart/w4"
|
||||||
"cart/w4"
|
|
||||||
"math/rand"
|
|
||||||
)
|
|
||||||
|
|
||||||
var gravity = 0.2
|
|
||||||
var points []*Point = []*Point{}
|
|
||||||
var sticks []*Stick = []*Stick{}
|
|
||||||
var player *Player
|
|
||||||
var frame uint64 = 0
|
var frame uint64 = 0
|
||||||
var lightIndex uint64 = 0
|
var stateUpdate func()
|
||||||
var camX int = 0
|
|
||||||
var camY int = 0
|
|
||||||
|
|
||||||
//go:export start
|
//go:export start
|
||||||
func start() {
|
func start() {
|
||||||
|
frame = 0
|
||||||
rand.Seed(654348654)
|
|
||||||
points = []*Point{}
|
|
||||||
sticks = []*Stick{}
|
|
||||||
w4.PALETTE[0] = 0xfcdeea
|
w4.PALETTE[0] = 0xfcdeea
|
||||||
w4.PALETTE[1] = 0x012824
|
w4.PALETTE[1] = 0x012824
|
||||||
w4.PALETTE[2] = 0x265935
|
w4.PALETTE[2] = 0x265935
|
||||||
w4.PALETTE[3] = 0xff4d6d
|
w4.PALETTE[3] = 0xff4d6d
|
||||||
|
|
||||||
for i := 0.0; i < 8; i++ {
|
menuStart()
|
||||||
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)],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:export update
|
//go:export update
|
||||||
func update() {
|
func update() {
|
||||||
frame += 1
|
frame++
|
||||||
*w4.DRAW_COLORS = 2
|
stateUpdate()
|
||||||
// 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)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
114
player.go
114
player.go
|
@ -7,39 +7,64 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Player struct {
|
type Player struct {
|
||||||
|
Index uint8
|
||||||
|
Health uint8
|
||||||
|
KilledBy Actor
|
||||||
Position Vector
|
Position Vector
|
||||||
Speed Vector
|
Speed Vector
|
||||||
//PointGrabbed *Point
|
|
||||||
StickGrabbed *Stick
|
StickGrabbed *Stick
|
||||||
StickOffset float64
|
StickOffset float64
|
||||||
GrabTimeout uint
|
GrabTimer uint8
|
||||||
|
ShootTimer uint8
|
||||||
|
ShootDirX int8
|
||||||
|
ShootDirY int8
|
||||||
Gamepad *uint8
|
Gamepad *uint8
|
||||||
GamepadLast 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)
|
lastGamepad := *p.Gamepad & (*p.Gamepad ^ p.GamepadLast)
|
||||||
p.GamepadLast = *p.Gamepad
|
p.GamepadLast = *p.Gamepad
|
||||||
if p.GrabTimeout > 0 {
|
if p.GrabTimer > 0 {
|
||||||
p.GrabTimeout--
|
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
|
isJumping := *p.Gamepad&w4.BUTTON_DOWN == 0
|
||||||
p.Speed.Y = math.Min(4, p.Speed.Y+gravity)
|
p.Speed.Y = math.Min(4, p.Speed.Y+gravity)
|
||||||
if p.StickGrabbed != nil {
|
if p.StickGrabbed != nil {
|
||||||
p.Speed.Y = 0
|
|
||||||
p.Speed.X = 0
|
p.Speed.X = 0
|
||||||
// p.Position = p.PointGrabbed.Position
|
p.Speed.Y = 0
|
||||||
if *p.Gamepad&w4.BUTTON_LEFT != 0 {
|
if *p.Gamepad&w4.BUTTON_1 == 0 {
|
||||||
p.Speed.X -= 1
|
p.Speed.X = float64(dirX)
|
||||||
}
|
p.Speed.Y = float64(dirY)
|
||||||
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.MoveOnRope(p.Speed)
|
p.MoveOnRope(p.Speed)
|
||||||
if p.StickOffset < 0 {
|
if p.StickOffset < 0 {
|
||||||
|
@ -62,9 +87,9 @@ func (p *Player) Update() {
|
||||||
}
|
}
|
||||||
p.Position = p.StickGrabbed.GetPosition(p.StickOffset)
|
p.Position = p.StickGrabbed.GetPosition(p.StickOffset)
|
||||||
if lastGamepad&w4.BUTTON_2 != 0 {
|
if lastGamepad&w4.BUTTON_2 != 0 {
|
||||||
p.GrabTimeout = 10
|
p.GrabTimer = 10
|
||||||
if isJumping {
|
if isJumping {
|
||||||
p.GrabTimeout = 10
|
p.GrabTimer = 10
|
||||||
p.Speed = p.Speed.MulScalar(2)
|
p.Speed = p.Speed.MulScalar(2)
|
||||||
if p.Speed.Y <= 0 {
|
if p.Speed.Y <= 0 {
|
||||||
p.Speed.Y -= 1 * 2
|
p.Speed.Y -= 1 * 2
|
||||||
|
@ -75,9 +100,17 @@ func (p *Player) Update() {
|
||||||
}
|
}
|
||||||
p.StickGrabbed = nil
|
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 {
|
} else {
|
||||||
p.Position.Move(p.Speed.X, p.Speed.Y)
|
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
|
distance := math.MaxFloat64
|
||||||
var selectedPoint *Point
|
var selectedPoint *Point
|
||||||
for _, point := range points {
|
for _, point := range points {
|
||||||
|
@ -98,7 +131,6 @@ func (p *Player) Update() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if stickDistance < 4 {
|
if stickDistance < 4 {
|
||||||
w4.Trace(strconv.FormatFloat(stickDistance, 'f', 3, 64))
|
|
||||||
p.StickGrabbed = selectedStick
|
p.StickGrabbed = selectedStick
|
||||||
p.StickOffset = selectedStick.GetOffset(p.Position)
|
p.StickOffset = selectedStick.GetOffset(p.Position)
|
||||||
p.StickGrabbed.PointA.Position.MoveVec(p.Speed)
|
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)
|
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) {
|
func (p *Player) MoveOnRope(motion Vector) {
|
||||||
|
@ -117,5 +154,36 @@ func (p *Player) MoveOnRope(motion Vector) {
|
||||||
|
|
||||||
func (p *Player) Draw() {
|
func (p *Player) Draw() {
|
||||||
*w4.DRAW_COLORS = 0x34
|
*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
|
Position Vector
|
||||||
PreviousPosition Vector
|
PreviousPosition Vector
|
||||||
IsLocked bool
|
IsLocked bool
|
||||||
TimeOffset uint64
|
TimeOffset uint16
|
||||||
Sticks []*Stick
|
Sticks []*Stick
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,14 +24,15 @@ func (p *Point) GetMotion() Vector {
|
||||||
|
|
||||||
func (p *Point) Draw() {
|
func (p *Point) Draw() {
|
||||||
*w4.DRAW_COLORS = 0x31
|
*w4.DRAW_COLORS = 0x31
|
||||||
fr := (frame + p.TimeOffset) % 60
|
fr := (frame + uint64(p.TimeOffset)) % 60
|
||||||
if fr > 20 {
|
if fr > 20 {
|
||||||
*w4.DRAW_COLORS = 0x32
|
|
||||||
}
|
|
||||||
if fr > 40 {
|
|
||||||
*w4.DRAW_COLORS = 0x34
|
*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)
|
w4.Oval(int(p.Position.X)-2-camX, int(p.Position.Y)-2-camY, 4, 4)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Stick struct {
|
type Stick struct {
|
||||||
|
@ -129,7 +130,7 @@ func CreateRope(start Vector, end Vector, divisions int) ([]*Point, []*Stick) {
|
||||||
Position: pos,
|
Position: pos,
|
||||||
PreviousPosition: pos,
|
PreviousPosition: pos,
|
||||||
IsLocked: (i == 0 || i == divisions),
|
IsLocked: (i == 0 || i == divisions),
|
||||||
TimeOffset: lightIndex * 153,
|
TimeOffset: uint16(lightIndex * 147),
|
||||||
}
|
}
|
||||||
lightIndex++
|
lightIndex++
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
|
|
Loading…
Reference in New Issue