Dev Blog | Comet

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...

  1. How i'm making the ring of light
  2. How I draw the lantern and make it animate when I walk.
  3. My fade up from black screen transition effect
  4. And a small one, talking about camera follow.

Animation1

~~ 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 :pensive:.

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 drawing 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.
Animation2

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 :clap::clap::clap: (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 ~~

Animation3

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.
Lamp-Sheet
Lamplight0-table-8-8 Lamplight1-table-8-8

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 ~~
Animation4

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.
Animation5

~~ Camera changing focus ~~
Animation7

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.

Animation6

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!

14 Likes