Example #1
0
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)
}
Example #2
0
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
		}
	}
}
Example #3
0
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()
}
Example #4
0
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)
}