Whoops! You need flash 10.1 or better for this.

###Setup### // create common funcs function drawBeaver( x, y, facing, step, depth ) { var stepSin = Math.sin( step * Math.PI ); // beaver tail drawRoundedRect( 0.15, 0.2, 0.2, 1, x - facing * 10, y, 10, 25, 5, 5 ); // beaver body drawRoundedRect( 0.1, 0.2, 0.5, 1, x, y - 15, 10, 15, 5, 5 ); drawRect( 0.1, 0.2, 0.5, 1, x, y - 5, 10, 5 ); drawBlob( 0.1, 0.2, 0.5, 1, x, y, 10, 30 ); // beaver arms drawBlob( 0.15, 0.2, 0.7, 1, x + 5 + 4 * facing, y + stepSin * 3, 3, 7 ); drawBlob( 0.15, 0.2, 0.7, 1, x - 5 + 4 * facing, y - stepSin * 3, 3, 7 ); // beaver feet drawBlob( 0.15, 0.2, 0.2, 1, x + 5 + 2 * facing, y - 28 - Math.min( stepSin, 0 ) * 5, 4, 2 ); drawBlob( 0.15, 0.2, 0.2, 1, x - 5 + 2 * facing, y - 28 + Math.max( stepSin, 0 ) * 5, 4, 2 ); // beaver face drawRoundedRect( 1, 1, 1, 1, x + 4 * facing, y + 15, 4, 5, 2, 2 ); drawBlob( 0.15, 0.2, 0.7, 1, x + 5 * facing, y + 20, 6, 5 ); drawFixedCircle( 0, 0, 0, 1, x + 3 + 4 * facing, y + 25, 2 ); drawFixedCircle( 0, 0, 0, 1, x - 3 + 4 * facing, y + 25, 2 ); // beaver arms // water overlay drawRect( 0.6, 0.4, 0.5, 0.75, x, y - 30, 20, depth ); // debug bounds overlay if( false && Math.random() < 0.5 ) { drawRect( 1, 1, 1, 0.25, x, y, 10, 30 ); } } // start it up //setPage( "BeaverRenderTest" ); //setPage( "Game" ); setPage( "StartButton" ); ###BeaverRenderTest### var time = 0; function update() { time += delta; } function render() { fillBackground( 0.6, 0.4, 0.5 ); drawBeaver( 0, 0, Math.sin( time ), ( time % 1 ) * 2 - 1, Math.sin( time ) * 3 + 10 ); } ###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: -180, y: 0, score: 0, hitCooldown: 0 } ); players.push( {x: 180, y: 0, score: 0, hitCooldown: 0 } ); var ball; var time = 0; var winCooldown = 0; function newBall() { ball = { x:0, y:0, dx: Math.random() > 0.5 ? -200 : 200, dy: Math.random() * 200 - 100, hitCount: 0, sx: 0, sy: 0 }; } function update() { // timers time += delta; for( player in players ) { player.hitCooldown = Math.max( player.hitCooldown - delta, 0 ); } if( winCooldown > 0 ) { winCooldown -= delta; if( winCooldown <= 0 ) { setPage( "StartButton" ); } } // move player paddle if( hasMouse ) { players[0].y = Math.min( Math.max( mouseY, -120 ), 110 ); } // 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 ), 110 ); // move ball if( winCooldown == 0 ) { ball.x += ball.dx * delta; ball.y += ball.dy * delta; // bounce ball if( ball.y < -120 ) { ball.y = -120; ball.dy = Math.abs( ball.dy ); playNote( 0, 0, 1, 0, 1, 0, ball.x ); } if( ball.y > 100 ) { ball.y = 100; ball.dy = -Math.abs( ball.dy ); playNote( 0, 0, 1, 0, 1, 0, ball.x ); } // endzones var scored = false; if( ball.x > 270 ) { players[0].score += 1; scored = true; if( players[0].score >= 3 ) { winCooldown = 3; } else { newBall(); } } if( ball.x < -270 ) { players[1].score += 1; scored = true; if( players[1].score >= 3 ) { winCooldown = 3; } else { newBall(); } } if( scored ) { for( i in 0...3 ) { playNote( 12, 12, 1, 0, 0.2, 0.2, -ball.x, 0 + i * 3 ); playNote( 16, 16, 1, 0, 0.2, 0.2, -ball.x, 1 + i * 3 ); playNote( 19, 19, 1, 0, 0.2, 0.2, -ball.x, 2 + i * 3 ); } } // 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, 12, 0, 1, 1, 0.2, player.x, 0 ); playNote( 12, 24, 1, 1, 0.2, 0.2, player.x, 1 ); playNote( 24, 24, 1, 0, 0.2, 1, player.x, 2 ); player.hitCooldown = 1; } } // feathers if( ball.x != ball.sx || ball.y != ball.sy ) { var oldLength = Math.pow( Math.pow( ball.x - ball.sx, 2 ) + Math.pow( ball.y - ball.sy, 2 ), 0.5 ); ball.sx = ball.x + ( ball.sx - ball.x ) * 30 / oldLength; ball.sy = ball.y + ( ball.sy - ball.y ) * 30 / oldLength; } } } function render() { // calc height of water var depth = Math.sin( time ) * 3 + 10; // actual background, as water fillBackground( 0.6, 0.4, 0.5 ); // upper ground drawRect( 0.3, 0.7, 0.5, 1, 0, 140, 240, 20 ); drawRect( 0.3, 0.7, 0.6, 1, 0, 115, 240, 5 ); drawRect( 0.1, 0.2, 0.6, 1, 0, 100, 240, 10 ); // water overlay drawRect( 0.6, 0.4, 0.5, 0.75, 0, 90, 240, depth ); // beavers for( player in players ) { var hit = player.hitCooldown * player.hitCooldown; var facing = player.x < 0 ? 1 : -1; drawBeaver( player.x, player.y, facing * ( 1 - hit ) - facing * hit, ( ( player.y * 0.02) % 1.0 ) * 2 - 1, depth ); } // ball translate( ball.x, ball.y ); stretch( Math.pow( ball.dx * ball.dx + ball.dy * ball.dy, 0.5 ) * 0.0003 + 1, Math.atan2( -ball.dy, ball.dx ) ); if( ball.sx != ball.x || ball.sy != ball.y ) { var featherAngle = Math.atan2( -( ball.sy - ball.y ), ball.sx - ball.x ) + Math.PI / 2; drawArc( 1, 1, 1, 0.5, 0, 0, 20, 20, featherAngle - Math.PI / 6, featherAngle + Math.PI / 6, 3 ); } drawBlob( 1, 0.6, 0.5, 1, 0, 0, 10, 10, 8 ); crosshairTransform(); // score flowers for( player in players ) { for( score in 0...3 ) { var x = ( -score * 30 + 150 ) * ( player.x < 0 ? -1 : 1 ); var y = 150 - Math.sin( x * 0.005 * Math.PI * 2 + 1 ) * 4; // flower stem drawRoundedRect( 0.3, 0.8, 0.3, 1, x, y - 10, 2, 10, 2, 2 ); if( score < player.score ) { // flower! translate( x, y ); rotate( Math.PI / 4 ); drawRoundedRect( 0.7, 0.8, 0.9, 1, 0, 0, 4, 8, 4, 4 ); rotate( Math.PI / 2 ); drawRoundedRect( 0.7, 0.8, 0.9, 1, 0, 0, 4, 8, 4, 4 ); drawFixedCircle( 0.16, 1, 0.5, 1, 0, 0, 3 ); crosshairTransform(); } else { // bud drawFixedCircle( 0.3, 0.8, 0.2, 1, x, y, 4 ); } } } // lower ground drawRect( 0.3, 0.7, 0.4, 1, 0, -140, 240, 20 ); } newBall(); [/gamesketch]

Is this what beavers look like? I really don't know. Regardless, I think I'm going to call this game done. I'm about three hours in now, and it's been fun. So there's that. I'm less confident about making games in under an hour but I'll keep at it. Maybe I'll speed up.

Any suggestions for the next microgame?

<3
Farbs

EDIT: I added a few new primitives to the renderer, including arcs, which reminded me that I hadn't finished the shuttlecock. So I finished the shuttlecock.


7 Comments » for Beaver Badminton, Part The Second
  1. Laremere@gmail.com says:

    Dystopian themed breakout.

  2. Jiggens says:

    Welcome back! Good to see you about again after quite a while!

  3. RandomCommander says:

    Well, we’re both back after a long while!

    I suggest maybe “Ninja Nonsense?” (Space invaders style, wherein a ninja fights many types of enemies per level (Like samurai the first, robots the second and policemen the third, so on so forth). 3 levels of this seems like a decent mini-project.)

  4. Farbs says:

    @Laremere – Hmm… interesting. I have an idea that _might_ work.

    @Jiggens – Cheers! I’ve been working pretty hard but just haven’t found time to update the blog much. In fact, I don’t think I ever even posted about finishing and releasing Captain Foraxian EX, which is a nice native windows spin on Captain Foraxian, and part of the Captain Forever supporter stuff.

    I wonder how long that twitter plugin has been broken. Erp. I think I’ll just remove that for now…

  5. Farbs says:

    @RandomCommander – Interestingly, I was thinking the postapocabreakout game might have some space invaderness to it. I would like to build the occasional series of these though, and yeah something like your suggestion would be about right for it.

  6. Jiggens says:

    @farbs
    I don’t think you did. I found it by accident when I checked your twitter that day. It was like a hidden present. A captain something present. The two best kinds.

  7. Well i can not win.
    Apperanlty,No one wins this game!