My plan for my second post was to catch everyone up with what I've already done so going forward, I can just start talk about the new things i've been working on but the performance issues in my game were bigger than I realised.
I have managed to squeeze in one visual flourish since the last post tho.
In this post I will explain 4 features...
- How i'm making the ring of light
- How I draw the lantern and make it animate when I walk.
- My fade up from black screen transition effect
- And a small one, talking about camera follow.
⠀
~~ RING OF LIGHT V2 ~~
So I was fully expecting the fill
circles to be too much but had assumed If used draw
, it would be okay.
No luck .
I had made a different thread where I talk though the issues.
It's tough when the web player doesn't perform the same way as real hardware does so I was limited in how much I could test, needing to relying on kind people like @neven and @pichuscute from rngparty.com.
In short, i'm draw
ing far too much on the screen and the...
neat little loop
// This whole section controls the light around the player
if lightRadius<0 then
lightRadius = 0
elseif lightRadius>lightRadiusMax then
lightRadius = lightRadiusMax
end
redraw_x = 0
while redraw_x<screen_width do
redraw_y = 0
while redraw_y<screen_height do
check_x = centre_x
check_x -= lightRadius
if redraw_x<check_x then
draw "black" at redraw_x,redraw_y
end
check_x = centre_x
check_x += lightRadius
if redraw_x>check_x then
draw "black" at redraw_x,redraw_y
end
check_y = centre_y
check_y -= lightRadius
if redraw_y<check_y then
draw "black" at redraw_x,redraw_y
end
check_y = centre_y
check_y += lightRadius
if redraw_y>check_y then
draw "black" at redraw_x,redraw_y
end
redraw_y++
end
redraw_x++
end
pushed our poor little draw
event to it's limit.
Along side that, Shawn said that using config.follow = 1
Also incurs a performance hit as it "effectively dirties every tile every frame" which I can understand.
I was determined! So between waiting for people to test, I pushed forward in what my friend called "Meta Programming". The idea is you write second program to make your first program.
I decided to use my years of experience in the Google Sheets framework to create all the hard coded draw commands I needed at each light level.
I would draw out the black tiles on one page (Note the punch out for the lamp)
Then have the next page spit out all the draw commands.
I then saved an output for each light level and lined them up. Eliminated blanks and sorted them such that I could workout which tiles need be be drawn at each light level.
With some if statements I ended up with something like this...
Draw Code
if lightRadius<=1 then
// 3x3 circle
draw bit of "black" in the middle
end
if lightRadius<=2 then
// 5x5 circle
draw a little more of "black" in the middle
end
if lightRadius<=3 then
// 7x7 Circle
draw a round square of "black"
end
if lightRadius<=4 then
// 9x9 circle
draw quite a lot of "black"
end
if lightRadius<=5 then
// 11x11 grid
draw HEAPS of "black" everywhere
end
if lightRadius<=6 then
// 13x13 grid
draw ALL of the "black"
end
if lightRadius==0 then
// hide player and show outline when there's no light
hide
draw "bottom outline" at centre_x,centre_y
draw "top outline" at centre_x,playerheady
draw "!" at 12,5
draw just the missing bit of "black"
end
The good news is that outside, my game plays at an impressive 8 fps (Inside was fine)
This is huge improvement over the... checks notes... 0 fps I was previously getting.
So I will keep looking at this. Shawn has suggested that I could get something working with the frame manipulation method. So look out for a v3 in the future.
⠀
~~ Lantern UI and Animation ~~
The idea here is just expanding on Neven's portrait example.
For his game, he had 5 or so portraits with 9 tiles each.
In my game, I have 7 lamp states which are 15 tiles each. And 2 frames of animation.
HOT TIP!
Horizontal sprite sheets are nice to look at but since tiles import left to right, it's much nicer to import vertical sheets. It helps when you need to place and name them.
Yes I had to have 70 unique tile names. Google sheets once again comes in with the save.
I used the format "lamp{lightRadiusin}t1f{lampframe}"
lightRadiusin
is a variable for the light level- t1 - t15 for each tile
lampframe
is the frame of animation
Then started drawing the lamp based on my light radius and the lamp frame.
draw "lamp{lightRadiusin}t1f{lampframe}" at 1,2
draw "lamp{lightRadiusin}t2f{lampframe}" at 2,2
draw "lamp{lightRadiusin}t3f{lampframe}" at 3,2
draw "lamp{lightRadiusin}t4f{lampframe}" at 1,3
draw "lamp{lightRadiusin}t5f{lampframe}" at 2,3
draw "lamp{lightRadiusin}t6f{lampframe}" at 3,3
draw "lamp{lightRadiusin}t7f{lampframe}" at 1,4
draw "lamp{lightRadiusin}t8f{lampframe}" at 2,4
draw "lamp{lightRadiusin}t9f{lampframe}" at 3,4
draw "lamp{lightRadiusin}t10f{lampframe}" at 1,5
draw "lamp{lightRadiusin}t11f{lampframe}" at 2,5
draw "lamp{lightRadiusin}t12f{lampframe}" at 3,5
draw "lamp{lightRadiusin}t13f{lampframe}" at 1,6
draw "lamp{lightRadiusin}t14f{lampframe}" at 2,6
draw "lamp{lightRadiusin}t15f{lampframe}" at 3,6
Here By default, it's always frame 0, but when I step I move it to frame 1. This creates a bobbing effect.
on update do
lampframe = 0
lampframe = 1
wait 0.3 then
lampframe = 0
end
You can see this idea done really well in @Harspoon 's Samurai Game for the sword health.
⠀
~~ Fade up from black screen transition ~~
This one is simple when you talk about it. Just draw black tiles on every tile of the screen, then do it again y-1.
But inner and outer loops are still a tongue twisters of the mind when I try and write them. After thinking I could do it alone, so I got some help. (Maybe I should start with a simple loop first.)
// transition effect
if fadevalue!=fadetarget then
if fadevalue>event.py then
hide
end
fadex = 0
while fadex<screen_width do
fadey = 0
while fadey<fadevalue do
draw "black" at fadex,fadey
fadey++
end
fadex++
end
fadevalue += fadedirerction
end
From here you define a few values and you're away.
on fade_to_black do
fadevalue = 0
fadetarget = screen_height
fadedirerction = 1
end
on fade_to_white do
fadevalue = screen_height
fadetarget = 0
fadedirerction = -1
end
The way this is done, you can actually made it fade any which way you want by changing the values up.
⠀
~~ Camera changing focus ~~
As we were building out the first version of the ring of light, my friend Dom asked if we should make the camera follow the player.
I thought this was a great idea as could help create a feeling of an unsafe world.
"It's all around me and I can't see it."
Then when you're inside, you can see everything and the world is still. Safe.
(It's subtle but I think it works.)
So I make sure every room declares what time of room it is.
on enter do
config.follow = 1 // 1 = camera follows the player
end
And I can then use that to determine how other elements of the game work.
For example, I only fade up when entering a light room.
⠀
One fun side effect of using a cantered camera and drawing on the full screen is you can actually draw outside of the room. And even animate it.
We theory crafted for a few mins on how we could use this to show part of the next room outside of the bounds of the current room but didn't go any further with it.
Perhaps that's something someone smarter than I can tackle.
⠀
Next up is still story stuff.
Planning to brainstorm ideas this weekend which has a reasonable scope.
Thanks for reading!