func (t *tileDynamic) Draw(ctx *html.Context, x, y int) { top := t.Connects(GetTile(x, y-1)) left := t.Connects(GetTile(x-1, y)) topLeft := t.Connects(GetTile(x-1, y-1)) right := t.Connects(GetTile(x+1, y)) topRight := t.Connects(GetTile(x+1, y-1)) bottom := t.Connects(GetTile(x, y+1)) bottomLeft := t.Connects(GetTile(x-1, y+1)) bottomRight := t.Connects(GetTile(x+1, y+1)) // Part 0 - Top Left t.computePart(0, top, left, topLeft, 0, 0) // Part 1 - Top Right t.computePart(1, top, right, topRight, 8, 0) // Part 2 - Bottom Left t.computePart(2, bottom, left, bottomLeft, 0, 8) // Part 3 - Bottom Right t.computePart(3, bottom, right, bottomRight, 8, 8) ctx.Save() ctx.Translate(x*tileSize, y*tileSize) img := Images["tiles"] ctx.DrawImageSection(img, t.OX+t.Parts[0].OX, t.OY+t.Parts[0].OY, 8, 8, 0, 0, 8, 8) ctx.DrawImageSection(img, t.OX+t.Parts[1].OX, t.OY+t.Parts[1].OY, 8, 8, 8, 0, 8, 8) ctx.DrawImageSection(img, t.OX+t.Parts[2].OX, t.OY+t.Parts[2].OY, 8, 8, 0, 8, 8, 8) ctx.DrawImageSection(img, t.OX+t.Parts[3].OX, t.OY+t.Parts[3].OY, 8, 8, 8, 8, 8, 8) ctx.Restore() }
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 (m *Map) Draw(ctx *html.Context) { if m.dirty || m.cache == nil { m.dirty = false if m.cache == nil { m.cache = html.NewCanvas(m.Width*tileSize, m.Height*tileSize) } ctx := m.cache.Context() for x := 0; x < m.Width; x++ { for y := 0; y < m.Height; y++ { m.Tile(x, y).Draw(ctx, x, y) } } } ctx.DrawImageSection(m.cache, int(cameraX), int(cameraY), 400, 240, 0, 0, 400, 240) }
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 (p *Person) Draw(ctx *html.Context, delta float64) { var dist = 0.0 if player != nil { dx := player.X - p.X dy := player.Y - p.Y dist = dx*dx + dy*dy if dist > 70*70 { RemoveEntity(p) return } } 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 onGround && player != nil && dist < 20*20 { if p.panicTime > 0 { p.panicTime -= delta if p.HSpeed == 0 { p.HSpeed = math.Copysign(0.1, globalRand.Float64()-0.5) } else { p.HSpeed = math.Copysign(0.1, p.HSpeed) } } else { p.HSpeed = math.Copysign(0.1, p.X-player.X) } } if p.HSpeed != 0 { p.lastDir = math.Copysign(1, p.HSpeed) } if math.Abs(p.HSpeed) > 0.6 { p.HSpeed = math.Copysign(0.6, p.HSpeed) } p.X += p.HSpeed * delta if ok, nx, _ := p.Collides(); ok { p.X = nx p.panicTime = 60 p.HSpeed = 0 } 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 } img := p.Sprite 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*4, 24, 32, -12, -15, 24, 32) ctx.DrawImageSection(img, offset, p.animation*32*4+32, 24, 32, -12, -15, 24, 32) ctx.DrawImageSection(img, offset, p.animation*32*4+32*2, 24, 32, -12, -15, 24, 32) ctx.DrawImageSection(img, offset, p.animation*32*4+32*3, 24, 32, -12, -15, 24, 32) ctx.Restore() }
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 (ps *ParticleSystem) Draw(ctx *html.Context, delta float64) { living := 0 ctx.BeginPath() ctx.FillStyle = ps.Color ctx.Save() ctx.Translate(int(ps.X*tileSize), int(ps.Y*tileSize)) for _, p := range ps.particles { if p.Life > 15 { continue } living++ p.Life += delta p.X += p.DX p.Y += p.DY p.DX += 0.1 * delta ctx.Arc(int(p.X), int(p.Y), ps.Size, 0, math.Pi*2, false) ctx.ClosePath() } ctx.Fill() ctx.Restore() if living == 0 { RemoveEntity(ps) } }