Hello!
Have you ever looked at a webcomic and thought wow, this person is really talented? Have you ever then hit the First Comic button and seen where they started out, and how long ago? Have you been amazed at how their writing, illustration, layout, world, and any number of other things I don’t know about have developed in such a short time? I have. And because I like making games I’ve wondered if there was a way to do that with game development. And so I tried.
I’ve failed to make highly episodic games many times already, but nonetheless remain positive. Whereas Polychromatic Funk Monkey: The Series never got to the prototype stage, my flash (and now Haxe) skills are now strong enough that I can actually finish things. Whereas Little Sh*t Planet took hours of work per episode, the focussed code-only workflow I used for TickyTacky let me create something playable in just a few minutes. Whereas TickyTacky was finicky to code in and tedious to publish with, GameSketch is as easy as writing a blog post. In fact, GameSketch is a wordpress plugin, so it’s exactly as easy as writing a blog post. The game code is written directly into – and you might be able to guess where I’m going with this – a blog post. Like this one.
Tonight I’ll take GameSketch (I skimped on the name, but since it’s an internal tool I think that’s okay) out for its first run. Tonight, I’ll try to make, and publish, Pong In An Hour. Lan has suggested that I present it as Beavers playing Badminton. We’ll see how I go for time.
Speaking of time, it’s now 7:26pm. My time starts… after the jump!
7:38pm I have paddles and a ball, but when I test the code it silently fails. I forgot I didn’t have a debug flash player installed on this laptop. I won’t see any error messages, which is making this rather tricky! Luckily I can save and test very quickly, so I should catch errors as I make them. I hope. Back to it…
7:51pm Okay, fixed the error. That took far too long. Still, I’m just two score counters and some paddle collisions away from a playable game. Oh and an AI opponent. Hmm. Back to it.
###StartButton### showMouse(); var state = ""; var pressing = false; var cooldown = 1; function isOver() { return mouseX * mouseX + mouseY * mouseY < 80*80; } function refresh() { if( state == "done" ) { var s = ( 1 - cooldown ) * 4 + 1; crosshairTransform(); scale( s, s ); } fillBackground( 0, 0, 0 ); drawFixedCircle( 1, 0, ( state == "none" ? 0.5 : state == "over" || state == "done" ? 1 : 0.25 ) * cooldown * cooldown, 1, 0, 0, 80 ); drawRect( 0, 0, 0, 1, -15, 0, 10, 30 ); drawRect( 0, 0, 0, 1, 5, 0, 10, 20 ); drawRect( 0, 0, 0, 1, 25, 0, 10, 10 ); } function setButtonState( newState ) { if( state != newState && state != "done" ) { state = newState; refresh(); } } function update() { if( state != "done" ) { if( isOver() ) { setButtonState( mouseDown && pressing ? "down" : "over" ); } else { setButtonState( "none" ); } } else { cooldown -= delta; refresh(); if( cooldown <= 0 ) { setPage( "Game" ); } } } function onMouseUp() { if( isOver() ) { setButtonState( "done" ); } } function onMouseDown() { if( isOver() && state != "done" ) { playNote( 0 ); pressing = true; } else { pressing = false; } } function feedSynth() { if( state == "done" ) { playNote( 12, 12, cooldown * cooldown, cooldown * cooldown, 1-cooldown, 1-cooldown, 0, 1 ); } } mouseX = 1000; // hacky, assume mouse is a long way away at first setButtonState( "none" ); ###Game### hideMouse(); var players = []; players.push( {x: -200, y: 0, score: 0 } ); players.push( {x: 200, y: 0, score: 0 } ); var ball; function newBall() { ball = { x:0, y:0, dx: Math.random() > 0.5 ? -200 : 200, dy: Math.random() * 200 - 100, hitCount: 0 }; } function update() { // move player paddle if( hasMouse ) { players[0].y = Math.min( Math.max( mouseY, -120 ), 120 ); } // move ai paddle var aiDy = 0; var aiDelta = ball.y - players[1].y; if( aiDelta > 20 ) { aiDy = 300; } if( aiDelta < -20 ) { aiDy = -300; } players[1].y = Math.min( Math.max( players[1].y + aiDy * delta, -120 ), 120 ); // move ball ball.x += ball.dx * delta; ball.y += ball.dy * delta; // bounce ball if( ball.y < -150 ) { ball.y = -150; ball.dy = Math.abs( ball.dy ); playNote( 0 ); } if( ball.y > 150 ) { ball.y = 150; ball.dy = -Math.abs( ball.dy ); playNote( 0 ); } // endzones if( ball.x > 250 ) { players[0].score += 1; playNote( 24 ); newBall(); if( players[0].score >= 3 ) { setPage( "StartButton" ); } } if( ball.x < -250 ) { players[1].score += 1; playNote( 24 ); newBall(); if( players[1].score >= 3 ) { setPage( "StartButton" ); } } // paddle collisions for( player in players ) { if( Math.abs( ball.x - player.x ) < 20 && Math.abs( ball.y - player.y ) < 40 && ball.dx * player.x > 0) { // hit! ball.dx = ( ball.x < 0 ? 200 : -200 ) * ( 1 + ball.hitCount / 4 ); ball.dy = ( ball.y - player.y ) * 7 * ( 1 + ball.hitCount / 4 ); // ball.x = ( Math.abs( player.x ) - 20 ) * ( ball.x < 0 ? -1 : 1 ); ball.hitCount += 1; playNote( 12 ); } } } function render() { fillBackground( 0, 0, 0 ); drawFixedCircle( 1, 1, 1, 1, ball.x, ball.y, 10 ); for( player in players ) { drawRoundedRect( 1, 1, 1, 1, player.x, player.y, 10, 30, 5, 5 ); } for( player in players ) { for( score in 0...player.score ) { drawRoundedRect( 1, 1, 1, 1, ( score * 30 + 40 ) * ( player.x < 0 ? -1 : 1 ), 140, 10, 10, 5, 5 ); } } } newBall(); [/gamesketch]
8:22pm Here it is! It's Pong, it took an hour, and I'm okay with that. I cheated slightly and used a play button that I'd built earlier, but I expect that reuse will be pretty common with this project. It's still a long way short of Badminton Beavers, so I'll see if I can find a few snippets of time to rework this into something a bit more exciting. The core game took 3x as long as I expected, and I'd hoped to make each nicely polished plaything in an hour, so perhaps with another 2 hours' work I could get this done. Join me next time (possibly later tonight!) as I endeavour to find out.
<3
Farbs