Beispiel #1
0
func Paint(w wde.Window, rect image.Rectangle) {
	xOffset, yOffset := GetTopLeft()

	minX, maxX := rect.Min.X>>res.TileSize, (rect.Max.X-1)>>res.TileSize+1
	minY, maxY := rect.Min.Y>>res.TileSize, (rect.Max.Y-1)>>res.TileSize+1

	center := layout.Coord{ViewportWidth/2 - xOffset, ViewportHeight/2 - yOffset}
	for x := minX; x < maxX; x++ {
		for y := minY; y < maxY; y++ {
			res.Tile(space, res.Terrain, uint16(layout.GetSpace(x-xOffset, y-yOffset)), x, y)
			draw.Draw(scene, image.Rect(x<<res.TileSize, y<<res.TileSize, (x+1)<<res.TileSize, (y+1)<<res.TileSize), image.Transparent, image.ZP, draw.Src)
			if WireView() {
				tile := layout.Get(x-xOffset, y-yOffset)
				for i := len(tile) - 1; i > 0; i-- {
					res.Tile(scene, res.Terrain, uint16(tile[i]), x, y)
				}
			} else {
				for _, t := range layout.Get(x-xOffset, y-yOffset) {
					res.Tile(scene, res.Terrain, uint16(t), x, y)
				}
			}
			if VisibilityOn() && !layout.Visible(center, layout.Coord{x - xOffset, y - yOffset}) {
				res.Tile(scene, image.Black, 0, x, y)
			}
		}
	}

	mouseLock.Lock()
	if mouseValid {
		res.Tile(scene, res.Terrain, uint16(mouseTile), mouseCoord.X+xOffset, mouseCoord.Y+yOffset)
	}
	mouseLock.Unlock()

	draw.Draw(viewport, rect, space, rect.Min, draw.Src)
	draw.Draw(viewport, rect, scene, rect.Min, draw.Over)
	if LightsOn() {
		draw.DrawMask(viewport, rect, image.Black, image.ZP, light.Image(-xOffset, -yOffset), rect.Min.Add(light.Origin(-xOffset, -yOffset)), draw.Over)
	}

	w.Screen().CopyRGBA(viewport, viewport.Bounds())

	w.FlushImage(rect)
}
Beispiel #2
0
func (p *Player) dispatch(msgIn message.Receiver, messages message.Sender) {
	for msg := range msgIn {
		switch m := msg.(type) {
		case SetLocation:
			if p.x != m.X || p.y != m.Y {
				Invalidate(p.screenRect())
				p.x, p.y = m.X, m.Y

				if p.isLocalPlayer {
					atomic.StoreUint32(&playerFlags, m.Flags)
				}

				paintLock.RLock()
				p.paint.Sprite = uint16(m.Flags & packet.FlagSpriteMask)
				if p.paint.Sprite == res.HumanSuit && layout.Get(p.x, p.y).Space() {
					p.paint.Sprite = res.HumanSuitHelm
				}
				if p.paint.Changed.IsZero() {
					p.paint.From.X, p.paint.From.Y = p.x, p.y
				} else {
					p.paint.From = p.paint.To
				}
				p.paint.To.X, p.paint.To.Y = p.x, p.y
				p.paint.Changed = time.Now()
				paintLock.RUnlock()

				if p.isLocalPlayer {
					atomic.StoreInt64(&topLeftX, ViewportWidth/2-int64(p.x))
					atomic.StoreInt64(&topLeftY, ViewportHeight/2-int64(p.y))
				} else {
					Invalidate(p.screenRect())
				}
			}

		case packet.Despawn:
			paintLock.Lock()
			delete(paintContexts, &p.Actor)
			paintLock.Unlock()
			Invalidate(p.screenRect())

		default:
			messages <- m
		}
	}
	close(messages)
}
Beispiel #3
0
func (p *Player) Initialize() (message.Receiver, message.Sender) {
	msgIn, broadcast := p.Actor.Initialize()

	p.ID = <-nextPlayerID

	messages := make(chan message.Message)

	go func() {
		for msg := range msgIn {
			switch m := msg.(type) {
			case SendLocation:
				m <- packet.Packet{
					Location: &packet.Location{
						ID:    p.ID,
						Coord: layout.Coord{p.x, p.y},
					},
				}

			case packet.Location:
				dx, dy := m.Coord.X, m.Coord.Y
				// TODO: space logic
				if layout.Get(p.x+dx, p.y+dy).Passable() {
					p.x += dx
					p.y += dy

					go func(m SetLocation) {
						world.Send <- m
					}(SetLocation{
						ID:    p.ID,
						Actor: &p.Actor,
						Coord: layout.Coord{p.x, p.y},
					})
				}

			default:
				messages <- m
			}
		}
		close(messages)
	}()

	return messages, broadcast
}
Beispiel #4
0
func Paint(w wde.Window, rect image.Rectangle) {
	xOffset, yOffset := GetTopLeft()
	center := layout.Coord{ViewportWidth/2 - xOffset, ViewportHeight/2 - yOffset}

	if center != oldCenter || layout.Version() != oldVersion {
		oldCenter = center
		oldVersion = layout.Version()

		for x := 0; x <= ViewportWidth; x++ {
			for y := 0; y <= ViewportHeight; y++ {
				if layout.Visible(center, layout.Coord{x - xOffset, y - yOffset}) {
					res.Tile(terrain, res.Terrain, uint16(layout.GetSpace(x-xOffset, y-yOffset)), x, y)
					draw.Draw(terrain, image.Rect(x<<res.TileSize, y<<res.TileSize, (x+1)<<res.TileSize, (y+1)<<res.TileSize), image.Transparent, image.ZP, draw.Src)
					for _, t := range layout.Get(x-xOffset, y-yOffset) {
						if !t.NoClient() {
							res.Tile(terrain, res.Terrain, uint16(t), x, y)
						}
					}
				} else {
					res.Tile(terrain, image.Black, 0, x, y)
				}
			}
		}

		switch GetPlayerFlags() & packet.FlagSpriteMask {
		case packet.FlagEngineer:
			for x := 0; x <= ViewportWidth; x++ {
				for y := 0; y <= ViewportHeight; y++ {
					dx, dy := x-ViewportWidth/2, y-ViewportHeight/2
					dist := dx*dx + dy*dy
					if dist <= 3*3 && layout.Visible(center, layout.Coord{x - xOffset, y - yOffset}) {
						for _, t := range layout.Get(x-xOffset, y-yOffset) {
							if t >= layout.WireW && t <= layout.WireS {
								res.Tile(terrain, res.Terrain, uint16(t), x, y)
							}
						}
					}
				}
			}
		}
	}

	minX, maxX := rect.Min.X>>res.TileSize, (rect.Max.X-1)>>res.TileSize+1
	minY, maxY := rect.Min.Y>>res.TileSize, (rect.Max.Y-1)>>res.TileSize+1

	draw.Draw(sprites, sprites.Bounds(), image.Transparent, image.ZP, draw.Src)

	var pixOffset image.Point

	var hasAnimation image.Rectangle
	paintLock.Lock()
	for _, p := range paintContexts {
		if layout.Visible(center, p.To) {
			x1, y1 := p.From.X+xOffset, p.From.Y+yOffset
			x2, y2 := p.To.X+xOffset, p.To.Y+yOffset

			if minX <= x2 && x2 <= maxX && minY <= y2 && y2 <= maxY {
				interp := float32(time.Since(p.Changed)*5) / float32(time.Second)
				if interp >= 1 {
					res.Tile(sprites, res.Actors, p.Sprite, x2, y2)
				} else {
					toInvalidate := image.Rect(x1, y1, x1+1, y1+1).Union(image.Rect(x2, y2, x2+1, y2+1))
					if hasAnimation.Empty() {
						hasAnimation = toInvalidate
					} else {
						hasAnimation = hasAnimation.Union(toInvalidate)
					}
					if p == thePlayer.paint {
						pixOffset.X = int(float32((x1-x2)<<res.TileSize) * (1 - interp))
						pixOffset.Y = int(float32((y1-y2)<<res.TileSize) * (1 - interp))
						hasAnimation = viewport.Bounds()
					}
					res.TileFloat(sprites, res.Actors, p.Sprite, x1, y1, x2, y2, interp)
				}
			}
		}
	}
	paintLock.Unlock()

	draw.Draw(viewport, rect, terrain, rect.Min.Add(pixOffset), draw.Src)
	draw.Draw(viewport, rect, sprites, rect.Min.Add(pixOffset), draw.Over)
	draw.DrawMask(viewport, rect, image.Black, image.ZP, light.Image(-xOffset, -yOffset), rect.Min.Add(light.Origin(-xOffset, -yOffset)).Add(pixOffset), draw.Over)

	if image.Rect(0, 0, 1, 1).Overlaps(rect) {
		mouseTileLock.Lock()
		res.DrawString(viewport, mouseTileString, color.White, res.FontSmall, 1, 1)
		mouseTileLock.Unlock()
	}

	if !hasAnimation.Empty() {
		Invalidate(image.Rectangle{hasAnimation.Min.Mul(1 << res.TileSize), hasAnimation.Max.Mul(1 << res.TileSize)})
	}

	paints++
	/* // For debugging paints
	res.DrawString(viewport, strconv.FormatUint(paints, 10), color.White, res.FontSmall, 300, 1)
	draw.Draw(viewport, image.Rectangle{rect.Min, image.Pt(rect.Max.X+1, rect.Min.Y+1)}, image.White, image.ZP, draw.Src)
	draw.Draw(viewport, image.Rectangle{image.Pt(rect.Min.X-1, rect.Max.Y-1), rect.Max}, image.White, image.ZP, draw.Src)
	draw.Draw(viewport, image.Rectangle{rect.Min, image.Pt(rect.Min.X+1, rect.Max.Y+1)}, image.White, image.ZP, draw.Src)
	draw.Draw(viewport, image.Rectangle{image.Pt(rect.Max.X-1, rect.Min.Y-1), rect.Max}, image.White, image.ZP, draw.Src)
	//*/

	w.Screen().CopyRGBA(viewport, viewport.Bounds())

	w.FlushImage(rect)
}
Beispiel #5
0
func writeMapTest() {
	minX, minY, maxX, maxY := 0, 0, 0, 0
	layout.AllTiles(func(c layout.Coord, t layout.MultiTile) {
		if t.Space() {
			return
		}
		if c.X < minX {
			minX = c.X
		}
		if c.Y < minY {
			minY = c.Y
		}
		if c.X > maxX {
			maxX = c.X
		}
		if c.Y > maxY {
			maxY = c.Y
		}
	})
	minX--
	minY--
	maxX++
	maxY++

	dx := maxX - minX
	dy := maxY - minY
	dx++
	dy++

	buf := make([]byte, dx*dy+dy-1)
	i := 0
	for y := minY; y <= maxY; y++ {
		if i != 0 {
			buf[i] = '\n'
			i++
		}
		for x := minX; x <= maxX; x++ {
			t := layout.Get(x, y)
			if t.Space() {
				buf[i] = ' '
			} else if t.Door() {
				if t.Passable() {
					buf[i] = 'd'
				} else {
					buf[i] = 'D'
				}
			} else if t.Passable() {
				buf[i] = '_'
			} else if t.BlocksVision() {
				buf[i] = 'W'
			} else {
				buf[i] = 'G'
			}
			i++
		}
	}

	f, err := os.Create("map_test.go")
	if err != nil {
		panic(err)
	}
	fmt.Fprint(f, beforeTest)
	fmt.Fprint(f, "\n\ttop   = ", minY)
	fmt.Fprint(f, "\n\tleft  = ", minX)
	fmt.Fprint(f, "\n\tcheck = `", string(buf), "`\n")
	fmt.Fprint(f, afterTest)
	f.Close()
}