func (t *tileSolidColor) Draw(ctx *html.Context, x, y int) { x *= tileSize y *= tileSize color := html.NewRGBColor(t.R, t.G, t.B) ctx.FillStyle = color ctx.FillRect(x, y, tileSize, tileSize) }
func drawBackground(ctx *html.Context, delta float64) { ctx.FillStyle = html.NewRGBColor(0, 19, 41) ctx.FillRect(0, 0, 800, 480) ctx.BeginPath() ctx.ShadowBlur = 50 ctx.ShadowColor = html.NewRGBColor(220, 220, 220) ctx.FillStyle = html.NewRGBColor(255, 255, 255) ctx.Arc( 400+int(450*math.Cos(moonPosition)), 300+int(200*math.Sin(moonPosition)), 50, 0, math.Pi*2, false) ctx.Fill() moonPosition += delta * 0.001 ctx.ShadowBlur = 0 for i := 0; i < len(clouds); i++ { c := clouds[i] ctx.BeginPath() ctx.FillStyle = html.Color("rgba(255, 255, 255, 0.2)") ctx.Save() ctx.Translate(int(c.X), int(c.Y)) for _, p := range c.parts { ctx.Arc(p.X, p.Y, p.R, 0, math.Pi*2, false) ctx.ClosePath() } ctx.Fill() ctx.Restore() c.X += c.Speed if c.X > 820 { c.parts = c.parts[:0] c.init() c.X = -100 } } }
func (p *Player) Draw(ctx *html.Context, delta float64) { p.LX, p.LY = p.X, p.Y p.Y += 0.1 onGround, _, _ := p.Collides() p.Y = p.LY if math.Abs(p.HSpeed) > 0 { if math.Abs(p.HSpeed) > 0.012 { if onGround { p.HSpeed -= math.Copysign(0.01*delta, p.HSpeed) } else { p.HSpeed -= math.Copysign(0.001*delta, p.HSpeed) } } else { p.HSpeed = 0 } } if !onGround { p.VSpeed += 0.02 * delta } else { p.VSpeed = 0 } if p.VSpeed > 1 { p.VSpeed = 1 } if p.isKeyDown[html.KeyW] || p.isKeyDown[' '] { p.jumpDownFor += delta } else { p.jumpDownFor = 0 } if p.jumpDownFor > 0 && onGround { p.VSpeed = -0.5 } if p.isKeyDown[html.KeyD] && onGround { p.HSpeed = 0.2 } else if p.isKeyDown[html.KeyA] && onGround { p.HSpeed = -0.2 } if p.HSpeed != 0 { p.lastDir = math.Copysign(1, p.HSpeed) } p.X += 0.01 touchingWall, _, _ := p.Collides() p.X = p.LX if p.jumpDownFor > 3 && !onGround && touchingWall { p.HSpeed *= -1.2 p.VSpeed = -0.5 AddEntity(NewParticleSystem(ParticleCircle, html.NewRGBColor(128, 83, 45), 1, 10, p.X+0.75, p.Y)) } p.X -= 0.01 touchingWall, _, _ = p.Collides() p.X = p.LX if p.jumpDownFor > 3 && !onGround && touchingWall { p.HSpeed *= -1.2 p.VSpeed = -0.5 AddEntity(NewParticleSystem(ParticleCircle, html.NewRGBColor(128, 83, 45), 1, 20, p.X+0.75, p.Y)) } if math.Abs(p.HSpeed) > 0.6 { p.HSpeed = math.Copysign(0.6, p.HSpeed) } if p.leapTime > 0 { p.leapTime -= delta if p.leapTime <= 0 { p.HSpeed = p.leapDX p.VSpeed = p.leapDY } } else { p.leapTime = 0 if p.armLength > 10 { p.armLength -= delta * 2 } else { p.armLength = 10 } } p.X += p.HSpeed * delta if ok, nx, _ := p.Collides(); ok { p.X = nx } p.Y += p.VSpeed * delta if ok, _, ny := p.Collides(); ok { p.Y = ny p.VSpeed = 0 } if p.LX != p.X || p.LY != p.Y { p.animation = 1 } else { p.animation = 0 } if p.attackTime > 0 { p.attackTime -= delta if p.attackTime <= 0 { p.armParts[1].VX = -1 * p.lastDir p.armParts[2].VX = -0.5 * p.lastDir for _, e := range entities { if e == player { continue } if pr, ok := e.(*Person); ok { dx := pr.X - (p.X + p.armParts[1].X/tileSize) dy := pr.Y - (p.Y + p.armParts[1].Y/tileSize) if dx*dx+dy*dy < 3*3 { ps := NewParticleSystem(ParticleCircle, html.NewRGBColor(255, 0, 0), 1, 20, pr.X+0.7, pr.Y+0.2) AddEntity(ps) RemoveEntity(pr) kills++ name := "hit" if globalRand.Float64() < 0.5 { name = "hit2" } audio := js.Global.Get("Audio").New() if audio.Call("canPlayType", "audio/mpeg").Bool() { audio.Set("type", "audio/mpeg") audio.Set("src", "sound/"+name+".mp3") } else { audio.Set("type", "audio/ogg") audio.Set("src", "sound/"+name+".ogg") } audio.Set("volume", 0.4) audio.Call("play") } } } } } else { p.attackTime = 0 } img := Images["player"] p.animationTime += delta * 0.1 info := playerAnimationFrames[p.animation] frames := float64(info.Frames) if p.animationTime > frames { p.animationTime -= frames } offset := (int(p.animationTime) % info.Frames) * 24 ctx.Save() ctx.Translate(int(p.X*tileSize)+12, int(p.Y*tileSize)+16) ctx.Scale(p.lastDir, 1) ctx.DrawImageSection(img, offset, p.animation*32, 24, 32, -12, -15, 24, 32) ctx.Restore() p.armParts[0].X, p.armParts[0].Y = float64(info.OX), float64(info.OY) if p.lastDir < 0 { p.armParts[0].X = 24 - p.armParts[0].X } armLength := p.armLength for i := 0; i < 2; i++ { if dx, dy := p.armParts[i].X-p.armParts[i+1].X, p.armParts[i].Y-p.armParts[i+1].Y; dx*dx+dy*dy >= armLength*armLength { ang := math.Atan2(dx, dy) p.armParts[i+1].X = p.armParts[i].X - armLength*math.Sin(ang) p.armParts[i+1].Y = p.armParts[i].Y - armLength*math.Cos(ang) } p.armParts[i+1].X -= p.HSpeed * 10 p.armParts[i+1].Y -= p.VSpeed * 10 p.armParts[i+1].X += p.armParts[i+1].VX p.armParts[i+1].Y += p.armParts[i+1].VY if math.Abs(p.armParts[i+1].VX) > 0.01 { p.armParts[i+1].VX -= math.Copysign(delta*0.1, p.armParts[i+1].VX) } else { p.armParts[i+1].VX = 0 } if math.Abs(p.armParts[i+1].VY) > 0.01 { p.armParts[i+1].VY -= math.Copysign(delta*0.1, p.armParts[i+1].VY) } else { p.armParts[i+1].VY = 0 } if ok, _, _ := CheckCollision(&box{ x: (p.X * tileSize) + p.armParts[i+1].X - 1, y: (p.Y * tileSize) + p.armParts[i+1].Y - 1, w: 2, h: 2, }, 0, 0); !ok { p.armParts[i+1].Y += 0.1 * float64(i+1) } } ctx.Save() ctx.Translate(int(p.X*tileSize), int(p.Y*tileSize)) ctx.StrokeStyle = html.NewRGBColor(183, 107, 113) ctx.LineJoin = html.RoundJoin ctx.LineCap = html.Round ctx.LineWidth = 2 ctx.BeginPath() ctx.MoveTo(int(p.armParts[0].X), int(p.armParts[0].Y)) ctx.LineTo(int(p.armParts[1].X), int(p.armParts[1].Y)) ctx.LineTo(int(p.armParts[2].X), int(p.armParts[2].Y)) ctx.Stroke() ctx.StrokeStyle = html.NewRGBColor(155, 75, 82) ctx.LineWidth = 1 ctx.BeginPath() ctx.MoveTo(int(p.armParts[0].X+1), int(p.armParts[0].Y+1)) ctx.LineTo(int(p.armParts[1].X+1), int(p.armParts[1].Y+1)) ctx.LineTo(int(p.armParts[2].X+1), int(p.armParts[2].Y+1)) ctx.Stroke() ctx.Restore() }
func drawFrame(delta float64) { if delta > 2.5 { delta = 2.5 } limit := 20 for len(entities) < 100 && player != nil && limit > 0 { limit-- cx := float64(globalRand.Intn(25)) + 10 cy := float64(globalRand.Intn(25)) + 10 if globalRand.Float64() < 0.5 { cx, cy = -cx, -cy } cx += player.X cy += player.Y t := GetTile(int(cx), int(cy)) if t != Empty && !t.IsSolid() { AddEntity(NewPerson(cx, cy)) } } drawBackground(ctx, delta) if moonPosition > math.Pi*2 && player != nil { // Game over RemoveEntity(player) AddEntity(NewParticleSystem(ParticleSquare, html.NewRGBColor(0, 255, 0), 2, 30, player.X, player.Y)) AddEntity(NewParticleSystem(ParticleSquare, html.NewRGBColor(0, 0, 255), 1, 30, player.X, player.Y)) player = nil audio := js.Global.Get("Audio").New() if audio.Call("canPlayType", "audio/mpeg").Bool() { audio.Set("type", "audio/mpeg") audio.Set("src", "sound/bang.mp3") } else { audio.Set("type", "audio/ogg") audio.Set("src", "sound/bangaaa.ogg") } audio.Set("volume", 0.4) audio.Call("play") } // Move the camera to the player if player != nil { targetX := player.X*tileSize - 100 cameraX += (targetX - cameraX) * 0.2 * delta if cameraX < 0 { cameraX = 0 } targetY := player.Y*tileSize - 100 cameraY += (targetY - cameraY) * 0.2 * delta if cameraY < 0 { cameraY = 0 } } ctx.Save() ctx.Scale(2, 2) Levels[currentMap].Draw(ctx) ctx.Translate(-int(cameraX), -int(cameraY)) DrawEntities(ctx, delta) ctx.Restore() ctx.FillStyle = html.NewRGBColor(0, 0, 0) ctx.FillRect(0, GameArea, 800, 480-GameArea) html.RequestFrame(drawFrame) ctx.FillStyle = html.NewRGBColor(255, 255, 255) ctx.Font = "32px monospaced" ctx.TextBaseline = html.Top ctx.FillText("Kills: "+strconv.Itoa(kills), 10, GameArea+10) }