@@ -67,13 +67,10 @@ type Camera struct {
67
67
sky * ebiten.Image
68
68
69
69
//--texture width--//
70
- texWidth int
71
-
72
- //--slices--//
73
- s []* image.Rectangle
70
+ texSize int
74
71
75
72
//--structs that contain rects and tints for each level render--//
76
- levels []* Level
73
+ levels []* level
77
74
78
75
// zbuffer for sprite casting
79
76
zBuffer []float64
@@ -83,18 +80,17 @@ type Camera struct {
83
80
spriteOrder []int
84
81
spriteDistance []float64
85
82
86
- spriteLvls []* Level
83
+ spriteLvls []* level
87
84
tex * TextureHandler
88
85
89
- floorLvl * HorLevel
86
+ floorLvl * horLevel
90
87
91
88
// used for concurrency
92
89
semaphore chan struct {}
93
90
}
94
91
95
92
// NewCamera initalizes a Camera object
96
- func NewCamera (width int , height int , texWid int , mapObj Map , slices []* image.Rectangle ,
97
- levels []* Level , horizontalLevel * HorLevel , spriteLvls []* Level , tex * TextureHandler ) * Camera {
93
+ func NewCamera (width int , height int , texSize int , mapObj Map , tex * TextureHandler ) * Camera {
98
94
99
95
fmt .Printf ("Initializing Camera\n " )
100
96
@@ -121,12 +117,11 @@ func NewCamera(width int, height int, texWid int, mapObj Map, slices []*image.Re
121
117
c .w = width
122
118
c .h = height
123
119
c .pitch = 0
124
- c .texWidth = texWid
125
- c .s = slices
126
- c .levels = levels
120
+ c .texSize = texSize
121
+ c .tex = tex
127
122
128
- c .floorLvl = horizontalLevel
129
- c .spriteLvls = spriteLvls
123
+ c .levels = c . createLevels ( mapObj . NumLevels ())
124
+ c .floorLvl = c . createFloorLevel ()
130
125
131
126
// set zbuffer based on screen width
132
127
c .zBuffer = make ([]float64 , width )
@@ -138,7 +133,7 @@ func NewCamera(width int, height int, texWid int, mapObj Map, slices []*image.Re
138
133
c .mapHeight = len (firstLevel )
139
134
140
135
c .sprites = []Sprite {}
141
- c .tex = tex
136
+ c .updateSpriteLevels ( 16 )
142
137
143
138
// initialize a pool of channels to limit concurrent floor and sprite casting
144
139
// from https://pocketgophers.com/limit-concurrent-use/
@@ -150,10 +145,25 @@ func NewCamera(width int, height int, texWid int, mapObj Map, slices []*image.Re
150
145
return c
151
146
}
152
147
148
+ func (c * Camera ) SetFloorTexture (floor * ebiten.Image ) {
149
+ c .floor = floor
150
+ }
151
+
152
+ func (c * Camera ) SetSkyTexture (sky * ebiten.Image ) {
153
+ c .sky = sky
154
+ }
155
+
153
156
// Update - updates the camera view
154
157
func (c * Camera ) Update (sprites []Sprite ) {
155
158
// clear horizontal buffer by making a new one
156
- c .floorLvl .Clear (c .w , c .h )
159
+ c .floorLvl .clear (c .w , c .h )
160
+
161
+ if len (sprites ) != len (c .sprites ) {
162
+ // sprite buffer may need to be increased in size
163
+ c .updateSpriteLevels (len (sprites ))
164
+ } else {
165
+ c .clearAllSpriteLevel ()
166
+ }
157
167
158
168
//--do raycast--//
159
169
c .sprites = sprites
@@ -162,7 +172,7 @@ func (c *Camera) Update(sprites []Sprite) {
162
172
163
173
func (c * Camera ) raycast () {
164
174
// cast level
165
- numLevels := cap ( c . levels )
175
+ numLevels := c . mapObj . NumLevels ( )
166
176
var wg sync.WaitGroup
167
177
for i := 0 ; i < numLevels ; i ++ {
168
178
wg .Add (1 )
@@ -195,14 +205,7 @@ func (c *Camera) raycast() {
195
205
func (c * Camera ) asyncCastLevel (levelNum int , wg * sync.WaitGroup ) {
196
206
defer wg .Done ()
197
207
198
- var rMap [][]int
199
-
200
- numLevels := c .mapObj .NumLevels ()
201
- if levelNum < numLevels {
202
- rMap = c .mapObj .Level (levelNum )
203
- } else {
204
- rMap = c .mapObj .Level (numLevels - 1 ) // if above highest level just keep extending last one up
205
- }
208
+ rMap := c .mapObj .Level (levelNum )
206
209
207
210
for x := 0 ; x < c .w ; x ++ {
208
211
c .castLevel (x , rMap , c .levels [levelNum ], levelNum , wg )
@@ -222,7 +225,7 @@ func (c *Camera) asyncCastSprite(spriteNum int, wg *sync.WaitGroup) {
222
225
223
226
// credit : Raycast loop and setting up of vectors for matrix calculations
224
227
// courtesy - http://lodev.org/cgtutor/raycasting.html
225
- func (c * Camera ) castLevel (x int , grid [][]int , lvl * Level , levelNum int , wg * sync.WaitGroup ) {
228
+ func (c * Camera ) castLevel (x int , grid [][]int , lvl * level , levelNum int , wg * sync.WaitGroup ) {
226
229
var _cts , _sv []* image.Rectangle
227
230
var _st []* color.RGBA
228
231
@@ -356,17 +359,17 @@ func (c *Camera) castLevel(x int, grid [][]int, lvl *Level, levelNum int, wg *sy
356
359
wallX -= math .Floor (wallX )
357
360
358
361
//x coordinate on the texture
359
- texX := int (wallX * float64 (c .texWidth ))
362
+ texX := int (wallX * float64 (c .texSize ))
360
363
if side == 0 && rayDirX > 0 {
361
- texX = c .texWidth - texX - 1
364
+ texX = c .texSize - texX - 1
362
365
}
363
366
364
367
if side == 1 && rayDirY < 0 {
365
- texX = c .texWidth - texX - 1
368
+ texX = c .texSize - texX - 1
366
369
}
367
370
368
371
//--set current texture slice to be slice x--//
369
- _cts [x ] = c .s [texX ]
372
+ _cts [x ] = c .tex . slices [texX ]
370
373
371
374
//--set height of slice--//
372
375
_sv [x ].Min .Y = drawStart
@@ -445,14 +448,14 @@ func (c *Camera) castLevel(x int, grid [][]int, lvl *Level, levelNum int, wg *sy
445
448
currentFloorY := weight * floorYWall + (1.0 - weight )* rayPosY
446
449
447
450
var floorTexX , floorTexY int
448
- floorTexX = int (currentFloorX * float64 (c .texWidth )) % c .texWidth
449
- floorTexY = int (currentFloorY * float64 (c .texWidth )) % c .texWidth
451
+ floorTexX = int (currentFloorX * float64 (c .texSize )) % c .texSize
452
+ floorTexY = int (currentFloorY * float64 (c .texSize )) % c .texSize
450
453
451
454
//floor
452
455
// buffer[y][x] = (texture[3][texWidth * floorTexY + floorTexX] >> 1) & 8355711;
453
456
// the same vertical slice method cannot be used for floor rendering
454
457
floorTexNum := 0
455
- floorTex := c .floorLvl .TexRGBA [floorTexNum ]
458
+ floorTex := c .floorLvl .texRGBA [floorTexNum ]
456
459
457
460
//pixel := floorTex.RGBAAt(floorTexX, floorTexY)
458
461
pxOffset := floorTex .PixOffset (floorTexX , floorTexY )
@@ -472,11 +475,11 @@ func (c *Camera) castLevel(x int, grid [][]int, lvl *Level, levelNum int, wg *sy
472
475
pixel .B = uint8 (float64 (pixel .B ) * float64 (pixelSt .B ) / 256 )
473
476
474
477
//c.horLvl.HorBuffer.SetRGBA(x, y, pixel)
475
- pxOffset = c .floorLvl .HorBuffer .PixOffset (x , y )
476
- c .floorLvl .HorBuffer .Pix [pxOffset ] = pixel .R
477
- c .floorLvl .HorBuffer .Pix [pxOffset + 1 ] = pixel .G
478
- c .floorLvl .HorBuffer .Pix [pxOffset + 2 ] = pixel .B
479
- c .floorLvl .HorBuffer .Pix [pxOffset + 3 ] = pixel .A
478
+ pxOffset = c .floorLvl .horBuffer .PixOffset (x , y )
479
+ c .floorLvl .horBuffer .Pix [pxOffset ] = pixel .R
480
+ c .floorLvl .horBuffer .Pix [pxOffset + 1 ] = pixel .G
481
+ c .floorLvl .horBuffer .Pix [pxOffset + 2 ] = pixel .B
482
+ c .floorLvl .horBuffer .Pix [pxOffset + 3 ] = pixel .A
480
483
}
481
484
}()
482
485
}
@@ -513,7 +516,7 @@ func (c *Camera) castSprite(spriteOrdIndex int) {
513
516
var uDiv float64 = 1 / sprite .Scale ()
514
517
var vDiv float64 = 1 / sprite .Scale ()
515
518
516
- var vMove float64 = - (sprite .PosZ ()- 0.5 )* float64 (c .texWidth )* 2 + sprite .VerticalOffset ()
519
+ var vMove float64 = - (sprite .PosZ ()- 0.5 )* float64 (c .texSize )* 2 + sprite .VerticalOffset ()
517
520
518
521
vMoveScreen := int (vMove / transformY ) + c .pitch + int (c .posZ / transformY )
519
522
@@ -558,11 +561,11 @@ func (c *Camera) castSprite(spriteOrdIndex int) {
558
561
//3) it's on the screen (right)
559
562
//4) ZBuffer, with perpendicular distance
560
563
if transformY > 0 && stripe > 0 && stripe < c .w && transformY < c .zBuffer [stripe ] {
561
- var spriteLvl * Level
564
+ var spriteLvl * level
562
565
if ! renderSprite {
563
566
renderSprite = true
564
567
spriteLvl = c .makeSpriteLevel (spriteOrdIndex )
565
- spriteSlices = MakeSlices (spriteTexWidth , spriteTexHeight , spriteTexRect .Min .X , spriteTexRect .Min .Y )
568
+ spriteSlices = makeSlices (spriteTexWidth , spriteTexHeight , spriteTexRect .Min .X , spriteTexRect .Min .Y )
566
569
} else {
567
570
spriteLvl = c .spriteLvls [spriteOrdIndex ]
568
571
}
@@ -611,14 +614,51 @@ func (c *Camera) castSprite(spriteOrdIndex int) {
611
614
}
612
615
}
613
616
614
- func (c * Camera ) UpdateSpriteLevels (spriteLvls []* Level ) {
615
- // TODO: this should be refactored rather than bouncing it around between game/camera
616
- c .spriteLvls = spriteLvls
617
+ // creates level slices for raycasting each level
618
+ func (c * Camera ) createLevels (numLevels int ) []* level {
619
+ levelArr := make ([]* level , numLevels )
620
+
621
+ for i := 0 ; i < numLevels ; i ++ {
622
+ levelArr [i ] = new (level )
623
+ levelArr [i ].Sv = sliceView (c .w , c .h )
624
+ levelArr [i ].Cts = make ([]* image.Rectangle , c .w )
625
+ levelArr [i ].St = make ([]* color.RGBA , c .w )
626
+ levelArr [i ].CurrTex = make ([]* ebiten.Image , c .w )
627
+ }
628
+
629
+ return levelArr
630
+ }
631
+
632
+ // creates floor slices for raycasting floor
633
+ func (c * Camera ) createFloorLevel () * horLevel {
634
+ horizontalLevel := new (horLevel )
635
+ horizontalLevel .clear (c .w , c .h )
636
+ horizontalLevel .texRGBA = []* image.RGBA {c .tex .FloorTex }
637
+ return horizontalLevel
617
638
}
618
639
619
- func (c * Camera ) makeSpriteLevel (spriteOrdIndex int ) * Level {
620
- spriteLvl := new (Level )
621
- spriteLvl .Sv = SliceView (c .w , c .h )
640
+ // updates sprite slice array as a level
641
+ func (c * Camera ) updateSpriteLevels (spriteCapacity int ) {
642
+ if c .spriteLvls != nil {
643
+ capacity := len (c .spriteLvls )
644
+ if spriteCapacity <= capacity {
645
+ // no need to grow, just need to clear it out
646
+ c .clearAllSpriteLevel ()
647
+ return
648
+ }
649
+
650
+ for capacity <= spriteCapacity {
651
+ capacity *= 2
652
+ }
653
+
654
+ spriteCapacity = capacity
655
+ }
656
+ c .spriteLvls = make ([]* level , spriteCapacity )
657
+ }
658
+
659
+ func (c * Camera ) makeSpriteLevel (spriteOrdIndex int ) * level {
660
+ spriteLvl := new (level )
661
+ spriteLvl .Sv = sliceView (c .w , c .h )
622
662
spriteLvl .Cts = make ([]* image.Rectangle , c .w )
623
663
spriteLvl .St = make ([]* color.RGBA , c .w )
624
664
spriteLvl .CurrTex = make ([]* ebiten.Image , c .w )
@@ -628,6 +668,12 @@ func (c *Camera) makeSpriteLevel(spriteOrdIndex int) *Level {
628
668
return spriteLvl
629
669
}
630
670
671
+ func (c * Camera ) clearAllSpriteLevel () {
672
+ for i := 0 ; i < len (c .spriteLvls ); i ++ {
673
+ c .clearSpriteLevel (i )
674
+ }
675
+ }
676
+
631
677
func (c * Camera ) clearSpriteLevel (spriteOrdIndex int ) {
632
678
c .spriteLvls [spriteOrdIndex ] = nil
633
679
}
@@ -701,14 +747,6 @@ func (c *Camera) getValidCameraMove(moveX, moveY float64, checkAlternate bool) (
701
747
return posX , posY
702
748
}
703
749
704
- func (c * Camera ) SetFloorTexture (floor * ebiten.Image ) {
705
- c .floor = floor
706
- }
707
-
708
- func (c * Camera ) SetSkyTexture (sky * ebiten.Image ) {
709
- c .sky = sky
710
- }
711
-
712
750
// Set camera position vector
713
751
func (c * Camera ) SetPosition (pos * geom.Vector2 ) {
714
752
c .pos = pos
0 commit comments