Added npc labels. More mapgen stuff. (#449)

This commit is contained in:
Tim Sarbin 2020-06-25 00:39:09 -04:00 committed by GitHub
parent 0cef1b0a73
commit 6dae0097b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 162 additions and 6 deletions

View File

@ -12,6 +12,8 @@ type MapEntity interface {
Render(target d2render.Surface)
Advance(tickTime float64)
GetPosition() (float64, float64)
GetPositionF() (float64, float64)
Name() string
}
// mapEntity represents an entity on the map that can be animated
@ -169,3 +171,11 @@ func angleToDirection(angle float64) int {
func (m *mapEntity) GetPosition() (float64, float64) {
return float64(m.TileX), float64(m.TileY)
}
func (m *mapEntity) GetPositionF() (float64, float64) {
return float64(m.TileX) + (float64(m.subcellX)/5.0), float64(m.TileY) + (float64(m.subcellY)/5.0)
}
func (m *mapEntity) Name() string {
return ""
}

View File

@ -22,6 +22,7 @@ type NPC struct {
repetitions int
direction int
objectLookup *d2datadict.ObjectLookupRecord
name string
}
func CreateNPC(x, y int, object *d2datadict.ObjectLookupRecord, direction int) *NPC {
@ -39,6 +40,26 @@ func CreateNPC(x, y int, object *d2datadict.ObjectLookupRecord, direction int) *
result.SetMode(object.Mode, object.Class, direction)
result.mapEntity.directioner = result.rotate
switch object.Act {
case 1:
switch object.Id {
case 0:
result.name = "Gheed"
case 1:
result.name = "Cain"
case 2:
result.name = "Akara"
case 5:
result.name = "Kashya"
case 7:
result.name = "Warriv"
case 8:
result.name = "Charsi"
case 9:
result.name = "Andariel"
}
}
return result
}
@ -143,3 +164,7 @@ func (v *NPC) SetMode(animationMode, weaponClass string, direction int) error {
return err
}
func (m *NPC) Name() string {
return m.name
}

View File

@ -18,7 +18,7 @@ type Player struct {
Equipment d2inventory.CharacterEquipment
Id string
direction int
Name string
name string
nameLabel d2ui.Label
lastPathSize int
isInTown bool
@ -59,7 +59,7 @@ func CreatePlayer(id, name string, x, y int, direction int, heroType d2enum.Hero
composite: composite,
Equipment: equipment,
direction: direction,
Name: name,
name: name,
nameLabel: d2ui.CreateLabel(d2resource.FontFormal11, d2resource.PaletteStatic),
isRunToggled: true,
isInTown: true,
@ -126,9 +126,9 @@ func (v *Player) Render(target d2render.Surface) {
)
defer target.Pop()
v.composite.Render(target)
v.nameLabel.X = v.offsetX
v.nameLabel.Y = v.offsetY - 100
v.nameLabel.Render(target)
//v.nameLabel.X = v.offsetX
//v.nameLabel.Y = v.offsetY - 100
//v.nameLabel.Render(target)
}
func (v *Player) SetMode(animationMode, weaponClass string, direction int) error {
@ -177,3 +177,7 @@ func (v *Player) rotate(direction int) {
v.SetMode(newAnimationMode, v.weaponClass, direction)
}
}
func (v *Player) Name() string {
return v.name
}

View File

@ -267,6 +267,68 @@ func generateWilderness1Contents(mapEngine *d2mapengine.MapEngine, rect d2common
}
}
stuff := []*d2mapstamp.Stamp{
loadPreset(mapEngine, d2wilderness.StoneFill1, 0),
loadPreset(mapEngine, d2wilderness.StoneFill1, 1),
loadPreset(mapEngine, d2wilderness.StoneFill1, 2),
loadPreset(mapEngine, d2wilderness.StoneFill2, 0),
loadPreset(mapEngine, d2wilderness.StoneFill2, 1),
loadPreset(mapEngine, d2wilderness.StoneFill2, 2),
loadPreset(mapEngine, d2wilderness.Cottages1, 0),
loadPreset(mapEngine, d2wilderness.Cottages1, 1),
loadPreset(mapEngine, d2wilderness.Cottages1, 2),
loadPreset(mapEngine, d2wilderness.Cottages1, 3),
loadPreset(mapEngine, d2wilderness.Cottages1, 4),
loadPreset(mapEngine, d2wilderness.Cottages1, 5),
loadPreset(mapEngine, d2wilderness.FallenCamp1, 0),
loadPreset(mapEngine, d2wilderness.FallenCamp1, 1),
loadPreset(mapEngine, d2wilderness.FallenCamp1, 2),
loadPreset(mapEngine, d2wilderness.FallenCamp1, 3),
loadPreset(mapEngine, d2wilderness.Pond, 0),
loadPreset(mapEngine, d2wilderness.SwampFill1, 0),
loadPreset(mapEngine, d2wilderness.SwampFill2, 0),
}
mapEngine.PlaceStamp(denOfEvil, denOfEvilLoc.X, denOfEvilLoc.Y)
numPlaced := 0
for numPlaced < 25 {
stamp := stuff[rand.Intn(len(stuff))]
stampRect := d2common.Rectangle {
Left: rect.Left+ rand.Intn(rect.Width) - stamp.Size().Width,
Top: rect.Top+rand.Intn(rect.Height) - stamp.Size().Height,
Width: stamp.Size().Width,
Height: stamp.Size().Height,
}
if areaEmpty(mapEngine, stampRect) {
mapEngine.PlaceStamp(stamp, stampRect.Left, stampRect.Top)
numPlaced++
}
}
}
func areaEmpty(mapEngine *d2mapengine.MapEngine, rect d2common.Rectangle) bool {
mapHeight := mapEngine.Size().Height
mapWidth := mapEngine.Size().Width
if rect.Bottom() >= mapHeight || rect.Right() >= mapWidth {
return false
}
for y := rect.Top; y <= rect.Bottom(); y++ {
for x := rect.Left; x <= rect.Right(); x++ {
if len(mapEngine.Tile(x, y).Floors) == 0 {
continue
}
floor := mapEngine.Tile(x, y).Floors[0]
if floor.Style != 0 || floor.Sequence != 0 || floor.Prop1 != 1 {
return false
}
}
}
return true
}

View File

@ -240,6 +240,14 @@ func (mr *MapRenderer) renderDebug(debugVisLevel int, target d2render.Surface, s
}
}
func (mr *MapRenderer) WorldToScreen(x, y float64) (int, int) {
return mr.viewport.WorldToScreen(x, y)
}
func (mr *MapRenderer) WorldToScreenF(x, y float64) (float64, float64) {
return mr.viewport.WorldToScreenF(x, y)
}
func (mr *MapRenderer) renderTileDebug(ax, ay int, debugVisLevel int, target d2render.Surface) {
subTileColor := color.RGBA{R: 80, G: 80, B: 255, A: 50}
tileColor := color.RGBA{R: 255, G: 255, B: 255, A: 100}

View File

@ -51,6 +51,10 @@ func (v *Viewport) WorldToScreen(x, y float64) (int, int) {
return v.OrthoToScreen(v.WorldToOrtho(x, y))
}
func (v *Viewport) WorldToScreenF(x, y float64) (float64, float64) {
return v.OrthoToScreenF(v.WorldToOrtho(x, y))
}
func (v *Viewport) ScreenToWorld(x, y int) (float64, float64) {
return v.OrthoToWorld(v.ScreenToOrtho(x, y))
}
@ -81,6 +85,13 @@ func (v *Viewport) OrthoToScreen(x, y float64) (int, int) {
return orthoX, orthoY
}
func (v *Viewport) OrthoToScreenF(x, y float64) (float64, float64) {
camOrthoX, camOrthoY := v.getCameraOffset()
orthoX := x - camOrthoX + float64(v.screenRect.Left)
orthoY := y - camOrthoY + float64(v.screenRect.Top)
return orthoX, orthoY
}
func (v *Viewport) IsTileVisible(x, y float64) bool {
orthoX1, orthoY1 := v.WorldToOrtho(x-3, y)
orthoX2, orthoY2 := v.WorldToOrtho(x+3, y)

View File

@ -56,11 +56,14 @@ func (v *Game) Render(screen d2render.Surface) error {
v.gameClient.RegenMap = false
v.mapRenderer.RegenerateTileCache()
}
screen.Clear(color.Black)
v.mapRenderer.Render(screen)
if v.gameControls != nil {
v.gameControls.Render(screen)
}
return nil
}

View File

@ -3,6 +3,7 @@ package d2player
import (
"image/color"
"log"
"math"
"time"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
@ -37,6 +38,8 @@ type GameControls struct {
escapeMenu *EscapeMenu
inputListener InputCallbackListener
FreeCam bool
lastMouseX int
lastMouseY int
// UI
globeSprite *d2ui.Sprite
@ -44,6 +47,7 @@ type GameControls struct {
menuButton *d2ui.Sprite
skillIcon *d2ui.Sprite
zoneChangeText *d2ui.Label
nameLabel *d2ui.Label
runButton d2ui.Button
isZoneTextShown bool
actionableRegions []ActionableRegion
@ -76,6 +80,11 @@ func NewGameControls(hero *d2mapentity.Player, mapEngine *d2mapengine.MapEngine,
label.Color = color.RGBA{R: 255, G: 88, B: 82, A: 255}
label.Alignment = d2ui.LabelAlignCenter
nameLabel := d2ui.CreateLabel(d2resource.FontFormal11, d2resource.PaletteStatic)
nameLabel.Alignment = d2ui.LabelAlignCenter
nameLabel.SetText("")
nameLabel.Color = color.White
gc := &GameControls{
hero: hero,
mapEngine: mapEngine,
@ -84,6 +93,7 @@ func NewGameControls(hero *d2mapentity.Player, mapEngine *d2mapengine.MapEngine,
inventory: NewInventory(),
heroStats: NewHeroStats(),
escapeMenu: NewEscapeMenu(),
nameLabel: &nameLabel,
zoneChangeText: &label,
actionableRegions: []ActionableRegion{
{leftSkill, d2common.Rectangle{Left: 115, Top: 550, Width: 50, Height: 50}},
@ -191,12 +201,15 @@ func (g *GameControls) OnMouseButtonRepeat(event d2input.MouseEvent) bool {
}
func (g *GameControls) OnMouseMove(event d2input.MouseMoveEvent) bool {
mx, my := event.X, event.Y
g.lastMouseX = mx
g.lastMouseY = my
if g.escapeMenu.IsOpen() {
g.escapeMenu.OnMouseMove(event)
return false
}
mx, my := event.X, event.Y
for i := range g.actionableRegions {
// Mouse over a game control element
if g.actionableRegions[i].Rect.IsInRect(mx, my) {
@ -327,6 +340,26 @@ func (g *GameControls) updateLayout() {
// TODO: consider caching the panels to single image that is reused.
func (g *GameControls) Render(target d2render.Surface) {
for entityIdx := range *g.mapEngine.Entities() {
entity := (*g.mapEngine.Entities())[entityIdx]
if entity.Name() == "" {
continue
}
entScreenXf, entScreenYf := g.mapRenderer.WorldToScreenF(entity.GetPositionF())
entScreenX := int(math.Floor(entScreenXf))
entScreenY := int(math.Floor(entScreenYf))
if ((entScreenX-20) <= g.lastMouseX) && ((entScreenX+20) >= g.lastMouseX) &&
((entScreenY-80) <= g.lastMouseY) && (entScreenY>= g.lastMouseY) {
g.nameLabel.SetText(entity.Name())
g.nameLabel.SetPosition(entScreenX, entScreenY - 100)
g.nameLabel.Render(target)
break
}
}
g.inventory.Render(target)
g.heroStats.Render(target)
g.escapeMenu.Render(target)