diff --git a/SarahTheSpaceSpy.coffee/README.md b/SarahTheSpaceSpy.coffee/README.md new file mode 100644 index 0000000..13afb0f --- /dev/null +++ b/SarahTheSpaceSpy.coffee/README.md @@ -0,0 +1,3 @@ +A short story about a programmer, written in programming. + +Forked from [ncase/SarahTheSpaceSpy.js](https://gist.github.com/ncase/6451ba18325edac8681d) \ No newline at end of file diff --git a/SarahTheSpaceSpy.coffee/SarahTheSpaceSpy.coffee b/SarahTheSpaceSpy.coffee/SarahTheSpaceSpy.coffee new file mode 100644 index 0000000..7bc61dc --- /dev/null +++ b/SarahTheSpaceSpy.coffee/SarahTheSpaceSpy.coffee @@ -0,0 +1,94 @@ +StartDayAgain = -> + + do sarah.wakeUp + + # What if my life was like a movie? In space? + + sarah.goto "Bathroom" + sarah.exit sarah.pajamas + sarah.clean sarah + sarah.clean sarah.teeth + sarah.enter sarah.clothes + + # I'd jump into my spaceship, and fly off to + # Astroexplorer Headquarters, reporting for duty. + + sarah.goto "Garage" + sarah.enter sarah.car + sarah.goto "Monolith Software Corp." + sarah.exit sarah.car + sarah.goto "My Cubicle" + + # And I'd be the most popular gal on board. + # Everyone would love Agent #001, SARAH THE SPACE SPY + + if sarah.meets "coworker" then sarah.say "Hi." else sarah.say null + sarah.enter sarah.cubicle + + # Yes, Agent #001 uses her hacking skills to break into + # alien computer networks, steal their secret technology, + # and help humanity take over the galaxy! + + until isCurrentTime "12:30" + if numTasksLeft > 0 then do sarah.work else do sarah.pretendToWork + + # Hold up, gotta refuel my engines. + + sarah.exit sarah.cubicle + food.enter sarah + sarah.enter sarah.cubicle + + # And, back to my mission! You think SARAH THE SPACE SPY + # would simply walk away from a long list of impossible tasks? + # Ha! I may rest, but I do not give up. + # AGENT #001 NEVER GIVES UP. + + until isCurrentTime "17:00" + do sarah.pretendToWork + + # Even though SARAH THE SPACE SPY could take on the whole + # universe by herself, she's loyal to the human race. + # She's selfless. Always ready to take one for the team. + + until isCurrentTime "17:15" + do sarah.pretendToWork + + # Thanks to SARAH, humanity is safe once again. All in a day's work. + # Now, it's time to fly back to my planetary base station. + + sarah.enter sarah.car + sarah.goto "Home" + + # Fade to black. Roll credits. + + sarah.exit sarah.car + sarah.goto "Living Room" + + # Yeah. That would be a great movie. I'd totally watch it. + + sarah.watch "Classic Sci-fi Shows on Netflix" + sarah.watch "Space Documentaries on YouTube" + sarah.watch "funny cat gifs" + + # One day, I'll write up that sci-fi young adult novel. + # I swear! I made it my New Year's Resolution again this year, + # because I haven't given up. Agent #001 never gives up. + + sarah.goto "Bathroom" + sarah.exit sarah.clothes + food.exit sarah + sarah.clean sarah + sarah.clean sarah.teeth + sarah.enter sarah.pajamas + + # I'm just too busy... There's no time right now. + # I just gotta keep on working, keep on moving up, + # and one day, I'll have all the free time in the world! + # Then... Then, I can start living my life. + + sarah.goto "Bedroom" + do sarah.sleep + + # ...one day. + + do StartDayAgain \ No newline at end of file diff --git a/TONES.ASM/README.md b/TONES.ASM/README.md new file mode 100644 index 0000000..57199dc --- /dev/null +++ b/TONES.ASM/README.md @@ -0,0 +1 @@ +DOS (tasm) program that sets a custom handler for interrupt 9h to play a tone on every key press. \ No newline at end of file diff --git a/TONES.ASM/TONES.ASM b/TONES.ASM/TONES.ASM new file mode 100644 index 0000000..3150729 --- /dev/null +++ b/TONES.ASM/TONES.ASM @@ -0,0 +1,59 @@ +.model tiny +.386 +.code +org 100h +start: + ;; Save old interrupt handler + mov ax, 3509h ; DOS function: get address of INT 9h handler + int 21h ; Call DOS + mov [i9_or], bx ; Offset + mov [i9_or + 2], es ; Segment + + ;; Set new interrupt handler + cli ; Disable interruptions + lea dx, interr ; Load address of custom handler + mov ax, 2509h ; DOS function: replace handler for INT 9h + int 21h ; Call DOS + sti ; Re-enable interruptions + + ;; End program, TSR style + mov ax, 3100h ; DOS function: Terminate and stay resident + mov dx, 00ffh ; Keep 255 bytes resident + int 21h ; Call DOS + + i9_or dw ?, ? ; Here we save the DOS INT 9h handler + +interr proc far + sti ; Re-enable interruptions + + ;; Initialize the speaker + in al, 61h ; Get speaker status word + push ax ; Save status word + or al, 00000011b ; Turn speaker on + out 61h, al ; Send new status word to speaker + mov al, 60 ; Set initial tone + + ;; Play a tone on the speaker +L2: out 42h, al ; Send tone to timer chip + mov cx, 100 ; Set outer counter +L3: push cx ; Save inner counter + mov cx, 0D00h ; Set inner counter +L3a: loop L3a ; Loop until inner counter is 0 + pop cx ; Restore outer counter + loop L3 ; Loop until outer counter is 0 + sub al, 1 ; Change tone + jnz L2 ; Repeat until tone is 0 + + ;; Disable speaker + pop ax ; Restore original speaker status word + and al, 11111100b ; Turn speaker off + out 61h, al ; Send status word to speaker + + ;; Jump to the original keyboard handler + ;; The next two instructions set the return address on the stack + push word ptr [cs:i9_or + 2] + push word ptr [cs:i9_or] + retf ; Return from this procedure +interr endp + +end start diff --git a/breakout.coffee/README.md b/breakout.coffee/README.md new file mode 100644 index 0000000..be2fc8e --- /dev/null +++ b/breakout.coffee/README.md @@ -0,0 +1 @@ +Coffeescript implementation of the MDN Breakout tutorial from [developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript) \ No newline at end of file diff --git a/breakout.coffee/breakout.coffee b/breakout.coffee/breakout.coffee new file mode 100644 index 0000000..91a2663 --- /dev/null +++ b/breakout.coffee/breakout.coffee @@ -0,0 +1,155 @@ +canvas = document.getElementById "myCanvas" +ctx = canvas.getContext "2d" + +# Player + +score = 0 +lives = 3 + +drawScore = -> + ctx.font = "16px Arial" + ctx.fillStyle = "#0095DD" + ctx.fillText "Score: " + score, 8, 20 + +drawLives = -> + ctx.font = "16px Arial" + ctx.fillStyle = "#0095DD" + ctx.fillText "Lives: " + lives, canvas.width - 65, 20 + +# Ball + +x = canvas.width / 2 +y = canvas.height - 30 +dx = 2 +dy = -2 +ballRadius = 10 + +drawBall = -> + do ctx.beginPath + ctx.arc x, y, ballRadius, 0, Math.PI * 2 + ctx.fillStyle = "#0095DD" + do ctx.fill + do ctx.closePath + +# Paddle + +paddleHeight = 10 +paddleWidth = 75 +paddleX = (canvas.width - paddleWidth) / 2 +rightPressed = false +leftPressed = false + +drawPaddle = -> + do ctx.beginPath + ctx.rect paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight + ctx.fillStyle = "#0095DD" + do ctx.fill + do ctx.closePath + +# Bricks + +brickRowCount = 3 +brickColumnCount = 5 +brickWidth = 75 +brickHeight = 20 +brickPadding = 10 +brickOffsetTop = 30 +brickOffsetLeft = 30 +bricks = [] + +for c in [0 ... brickColumnCount] + bricks[c] = [] + for r in [0 ... brickRowCount] + bricks[c][r] = + x: (c * (brickWidth + brickPadding)) + brickOffsetLeft, + y: (r * (brickHeight + brickPadding)) + brickOffsetTop, + active: true + +drawBricks = -> + drawSingleBrick = (brick) -> + do ctx.beginPath + ctx.rect brick.x, brick.y, brickWidth, brickHeight + ctx.fillStyle = "#0095DD" + do ctx.fill + do ctx.closePath + + for col in bricks + for b in col + drawSingleBrick b if b.active + +collisionDetection = -> + for col in bricks + for b in col + if b.active and x > b.x and x < b.x + brickWidth and y > b.y and y < b.y + brickHeight + dy = -dy + b.active = false + score++ + if score == brickRowCount * brickColumnCount + alert "A winner is you!" + do document.location.reload + +# Game loop + +gameLoop = -> + ctx.clearRect 0, 0, canvas.width, canvas.height + do drawBricks + do drawBall + do drawPaddle + do drawScore + do drawLives + + do collisionDetection + + x += dx + y += dy + + dx = -dx if (x + dx > canvas.width - ballRadius) or (x + dx < ballRadius) + dy = -dy if (y + dy < ballRadius) + + if y + dy > canvas.height - ballRadius + if x > paddleX and x < paddleX + paddleWidth + dy = -dy - 0.25 + if dx >= 0 then dx += 0.25 else dx -= 0.25 + else + lives-- + if not lives + alert "Game over, man!" + do document.location.reload + else + x = canvas.width / 2 + y = canvas.height - 30 + dx = 2 + dy = -2 + paddleX = (canvas.width - paddleWidth) / 2 + + paddleX += 7 if rightPressed and paddleX < canvas.width - paddleWidth + paddleX -= 7 if leftPressed and paddleX > 0 + + requestAnimationFrame gameLoop + +# Input handlers + +keyDownHandler = (e) -> + if e.keyCode == 39 + rightPressed = true + else if e.keyCode == 37 + leftPressed = true + +keyUpHandler = (e) -> + if e.keyCode == 39 + rightPressed = false + else if e.keyCode == 37 + leftPressed = false + +mouseMoveHandler = (e) -> + hw = (paddleWidth / 2) + relativeX = e.clientX - canvas.offsetLeft + paddleX = relativeX - hw if relativeX > hw and relativeX < canvas.width - hw + +# Initialization + +document.addEventListener "keydown", keyDownHandler, false +document.addEventListener "keyup", keyUpHandler, false +document.addEventListener "mousemove", mouseMoveHandler, false + +do gameLoop \ No newline at end of file diff --git a/breakout.coffee/breakout.js b/breakout.coffee/breakout.js new file mode 100644 index 0000000..53c4685 --- /dev/null +++ b/breakout.coffee/breakout.js @@ -0,0 +1,234 @@ +// Generated by CoffeeScript 2.3.2 +(function() { + var ballRadius, brickColumnCount, brickHeight, brickOffsetLeft, brickOffsetTop, brickPadding, brickRowCount, brickWidth, bricks, c, canvas, collisionDetection, ctx, drawBall, drawBricks, drawLives, drawPaddle, drawScore, dx, dy, gameLoop, i, j, keyDownHandler, keyUpHandler, leftPressed, lives, mouseMoveHandler, paddleHeight, paddleWidth, paddleX, r, ref, ref1, rightPressed, score, x, y; + + canvas = document.getElementById("myCanvas"); + + ctx = canvas.getContext("2d"); + + // Player + score = 0; + + lives = 3; + + drawScore = function() { + ctx.font = "16px Arial"; + ctx.fillStyle = "#0095DD"; + return ctx.fillText("Score: " + score, 8, 20); + }; + + drawLives = function() { + ctx.font = "16px Arial"; + ctx.fillStyle = "#0095DD"; + return ctx.fillText("Lives: " + lives, canvas.width - 65, 20); + }; + + // Ball + x = canvas.width / 2; + + y = canvas.height - 30; + + dx = 2; + + dy = -2; + + ballRadius = 10; + + drawBall = function() { + ctx.beginPath(); + ctx.arc(x, y, ballRadius, 0, Math.PI * 2); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + return ctx.closePath(); + }; + + // Paddle + paddleHeight = 10; + + paddleWidth = 75; + + paddleX = (canvas.width - paddleWidth) / 2; + + rightPressed = false; + + leftPressed = false; + + drawPaddle = function() { + ctx.beginPath(); + ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + return ctx.closePath(); + }; + + // Bricks + brickRowCount = 3; + + brickColumnCount = 5; + + brickWidth = 75; + + brickHeight = 20; + + brickPadding = 10; + + brickOffsetTop = 30; + + brickOffsetLeft = 30; + + bricks = []; + + for (c = i = 0, ref = brickColumnCount; (0 <= ref ? i < ref : i > ref); c = 0 <= ref ? ++i : --i) { + bricks[c] = []; + for (r = j = 0, ref1 = brickRowCount; (0 <= ref1 ? j < ref1 : j > ref1); r = 0 <= ref1 ? ++j : --j) { + bricks[c][r] = { + x: (c * (brickWidth + brickPadding)) + brickOffsetLeft, + y: (r * (brickHeight + brickPadding)) + brickOffsetTop, + active: true + }; + } + } + + drawBricks = function() { + var b, col, drawSingleBrick, k, len, results; + drawSingleBrick = function(brick) { + ctx.beginPath(); + ctx.rect(brick.x, brick.y, brickWidth, brickHeight); + ctx.fillStyle = "#0095DD"; + ctx.fill(); + return ctx.closePath(); + }; + results = []; + for (k = 0, len = bricks.length; k < len; k++) { + col = bricks[k]; + results.push((function() { + var l, len1, results1; + results1 = []; + for (l = 0, len1 = col.length; l < len1; l++) { + b = col[l]; + if (b.active) { + results1.push(drawSingleBrick(b)); + } else { + results1.push(void 0); + } + } + return results1; + })()); + } + return results; + }; + + collisionDetection = function() { + var b, col, k, len, results; + results = []; + for (k = 0, len = bricks.length; k < len; k++) { + col = bricks[k]; + results.push((function() { + var l, len1, results1; + results1 = []; + for (l = 0, len1 = col.length; l < len1; l++) { + b = col[l]; + if (b.active && x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) { + dy = -dy; + b.active = false; + score++; + if (score === brickRowCount * brickColumnCount) { + alert("A winner is you!"); + results1.push(document.location.reload()); + } else { + results1.push(void 0); + } + } else { + results1.push(void 0); + } + } + return results1; + })()); + } + return results; + }; + + // Game loop + gameLoop = function() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + drawBricks(); + drawBall(); + drawPaddle(); + drawScore(); + drawLives(); + collisionDetection(); + x += dx; + y += dy; + if ((x + dx > canvas.width - ballRadius) || (x + dx < ballRadius)) { + dx = -dx; + } + if (y + dy < ballRadius) { + dy = -dy; + } + if (y + dy > canvas.height - ballRadius) { + if (x > paddleX && x < paddleX + paddleWidth) { + dy = -dy - 0.25; + if (dx >= 0) { + dx += 0.25; + } else { + dx -= 0.25; + } + } else { + lives--; + if (!lives) { + alert("Game over, man!"); + document.location.reload(); + } else { + x = canvas.width / 2; + y = canvas.height - 30; + dx = 2; + dy = -2; + paddleX = (canvas.width - paddleWidth) / 2; + } + } + } + if (rightPressed && paddleX < canvas.width - paddleWidth) { + paddleX += 7; + } + if (leftPressed && paddleX > 0) { + paddleX -= 7; + } + return requestAnimationFrame(gameLoop); + }; + + // Input handlers + keyDownHandler = function(e) { + if (e.keyCode === 39) { + return rightPressed = true; + } else if (e.keyCode === 37) { + return leftPressed = true; + } + }; + + keyUpHandler = function(e) { + if (e.keyCode === 39) { + return rightPressed = false; + } else if (e.keyCode === 37) { + return leftPressed = false; + } + }; + + mouseMoveHandler = function(e) { + var hw, relativeX; + hw = paddleWidth / 2; + relativeX = e.clientX - canvas.offsetLeft; + if (relativeX > hw && relativeX < canvas.width - hw) { + return paddleX = relativeX - hw; + } + }; + + // Initialization + document.addEventListener("keydown", keyDownHandler, false); + + document.addEventListener("keyup", keyUpHandler, false); + + document.addEventListener("mousemove", mouseMoveHandler, false); + + gameLoop(); + +}).call(this); \ No newline at end of file diff --git a/breakout.coffee/index.html b/breakout.coffee/index.html new file mode 100644 index 0000000..a92d110 --- /dev/null +++ b/breakout.coffee/index.html @@ -0,0 +1,15 @@ + + + + + Gamedev Canvas Workshop + + + + + + + \ No newline at end of file diff --git a/breakout_phaser.coffee/README.md b/breakout_phaser.coffee/README.md new file mode 100644 index 0000000..c2c476a --- /dev/null +++ b/breakout_phaser.coffee/README.md @@ -0,0 +1 @@ +Coffeescript implementation of the MDN Breakout tutorial with Phaser V2 from [developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Games/Tutorials/2D_breakout_game_Phaser/Randomizing_gameplay) \ No newline at end of file diff --git a/breakout_phaser.coffee/breakout_phaser.coffee b/breakout_phaser.coffee/breakout_phaser.coffee new file mode 100644 index 0000000..2d21c6b --- /dev/null +++ b/breakout_phaser.coffee/breakout_phaser.coffee @@ -0,0 +1,151 @@ +ball = null +paddle = null +bricks = null +newBrick = null +brickInfo = null +scoreText = null +score = 0 +textStyle = + font: "18px Arial" + fill: "#0095DD" +lives = 3 +livesText = null +lifeLostText = null +playing = false +startButton = null + +startGame = -> + do startButton.destroy + ball.body.velocity.set 150, -150 + playing = true + +ballLeaveScreen = -> + playing = false + lives-- + if lives + livesText.setText "Lives: " + lives + lifeLostText.visible = true + ball.reset game.world.width * 0.5, game.world.height - 25 + paddle.reset game.world.width * 0.5, game.world.height - 5 + game.input.onDown.addOnce -> + lifeLostText.visible = false + ball.body.velocity.set 150, -150 + playing = true + , this + else + alert "Game over, man!" + do location.reload + +initBricks = -> + brickInfo = + width: 50 + height: 20 + count: + row: 3 + col: 7 + offset: + top: 50 + left: 60 + padding: 10 + + bricks = do game.add.group + + for c in [0 ... brickInfo.count.col] + for r in [0 ... brickInfo.count.row] + brickX = (c * (brickInfo.width + brickInfo.padding)) + brickInfo.offset.left + brickY = (r * (brickInfo.height + brickInfo.padding)) + brickInfo.offset.top + newBrick = game.add.sprite brickX, brickY, "brick" + game.physics.enable newBrick, Phaser.Physics.ARCADE + newBrick.body.immovable = true + newBrick.anchor.set 0.5 + bricks.add newBrick + +ballHitBrick = (ball, brick) -> + target = + x: 0 + y: 0 + killTween = game.add.tween brick.scale + killTween.to target = + x: 0 + y: 0 + , 200, Phaser.Easing.Linear.None + killTween.onComplete.addOnce -> + do brick.kill + , this + do killTween.start + + score += 10 + scoreText.setText "Points: " + score + + if score == brickInfo.count.row * brickInfo.count.col * 10 + alert "A winner is you!" + do location.reload + + ball.animations.play "wobble" + +ballHitPaddle = (ball, paddle) -> + ball.animations.play "wobble" + ball.body.velocity.x = -1 * 5 * (paddle.x - ball.x) + +preload = -> + # Set basic game properties + game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL + game.scale.pageAlignHorizontally = true + game.scale.pageAlignVertically = true + game.stage.backgroundColor = "#eee" + + # Load texture images + game.load.image "paddle", "img/paddle.png" + game.load.image "brick", "img/brick.png" + game.load.spritesheet "ball", "img/wobble.png", 20, 20 + game.load.spritesheet "button", "img/button.png", 120, 40 + +create = -> + # Initialize the physics engine + game.physics.startSystem Phaser.Physics.ARCADE + game.physics.arcade.checkCollision.down = false + + # Create the ball sprite and set it"s properties + ball = game.add.sprite game.world.width * 0.5, game.world.height - 25, "ball" + ball.animations.add "wobble", [0, 1, 0, 2, 0, 1, 0, 2, 0], 24 + ball.anchor.set 0.5 + game.physics.enable ball, Phaser.Physics.ARCADE + ball.body.bounce.set 1 + ball.body.collideWorldBounds = true + ball.checkWorldBounds = true + ball.events.onOutOfBounds.add ballLeaveScreen, this + + # Create the paddle sprite and set it"s properties + paddle = game.add.sprite game.world.width * 0.5, game.world.height - 5, "paddle" + paddle.anchor.set 0.5, 1 + game.physics.enable paddle, Phaser.Physics.ARCADE + paddle.body.immovable = true + + # Brick creation + do initBricks + + # Scorekeeping + scoreText = game.add.text 5, 5, "Points: 0", textStyle + + # Player lives + livesText = game.add.text game.world.width - 5, 5, "Lives: " + lives, textStyle + livesText.anchor.set 1, 0 + lifeLostText = game.add.text game.world.width * 0.5, game.world.height * 0.5, 'Life lost, click to continue', textStyle + lifeLostText.anchor.set 0.5 + lifeLostText.visible = false + + # Start button + startButton = game.add.button game.world.width * 0.5, game.world.height * 0.5, "button", startGame, this, 1, 0, 2 + startButton.anchor.set 0.5 + +update = -> + game.physics.arcade.collide ball, paddle, ballHitPaddle + game.physics.arcade.collide ball, bricks, ballHitBrick + paddle.x = game.input.x or (game.world.width * 0.5) if playing + +functions = + preload: preload, + create: create, + update: update + +game = new Phaser.Game 480, 320, Phaser.CANVAS, null, functions \ No newline at end of file diff --git a/breakout_phaser.coffee/breakout_phaser.js b/breakout_phaser.coffee/breakout_phaser.js new file mode 100644 index 0000000..ee14c00 --- /dev/null +++ b/breakout_phaser.coffee/breakout_phaser.js @@ -0,0 +1,186 @@ +// Generated by CoffeeScript 2.3.2 +(function() { + var ball, ballHitBrick, ballHitPaddle, ballLeaveScreen, brickInfo, bricks, create, functions, game, initBricks, lifeLostText, lives, livesText, newBrick, paddle, playing, preload, score, scoreText, startButton, startGame, textStyle, update; + + ball = null; + + paddle = null; + + bricks = null; + + newBrick = null; + + brickInfo = null; + + scoreText = null; + + score = 0; + + textStyle = { + font: "18px Arial", + fill: "#0095DD" + }; + + lives = 3; + + livesText = null; + + lifeLostText = null; + + playing = false; + + startButton = null; + + startGame = function() { + startButton.destroy(); + ball.body.velocity.set(150, -150); + return playing = true; + }; + + ballLeaveScreen = function() { + playing = false; + lives--; + if (lives) { + livesText.setText("Lives: " + lives); + lifeLostText.visible = true; + ball.reset(game.world.width * 0.5, game.world.height - 25); + paddle.reset(game.world.width * 0.5, game.world.height - 5); + return game.input.onDown.addOnce(function() { + lifeLostText.visible = false; + ball.body.velocity.set(150, -150); + return playing = true; + }, this); + } else { + alert("Game over, man!"); + return location.reload(); + } + }; + + initBricks = function() { + var brickX, brickY, c, i, r, ref, results; + brickInfo = { + width: 50, + height: 20, + count: { + row: 3, + col: 7 + }, + offset: { + top: 50, + left: 60 + }, + padding: 10 + }; + bricks = game.add.group(); + results = []; + for (c = i = 0, ref = brickInfo.count.col; (0 <= ref ? i < ref : i > ref); c = 0 <= ref ? ++i : --i) { + results.push((function() { + var j, ref1, results1; + results1 = []; + for (r = j = 0, ref1 = brickInfo.count.row; (0 <= ref1 ? j < ref1 : j > ref1); r = 0 <= ref1 ? ++j : --j) { + brickX = (c * (brickInfo.width + brickInfo.padding)) + brickInfo.offset.left; + brickY = (r * (brickInfo.height + brickInfo.padding)) + brickInfo.offset.top; + newBrick = game.add.sprite(brickX, brickY, "brick"); + game.physics.enable(newBrick, Phaser.Physics.ARCADE); + newBrick.body.immovable = true; + newBrick.anchor.set(0.5); + results1.push(bricks.add(newBrick)); + } + return results1; + })()); + } + return results; + }; + + ballHitBrick = function(ball, brick) { + var killTween, target; + target = { + x: 0, + y: 0 + }; + killTween = game.add.tween(brick.scale); + killTween.to(target = { + x: 0, + y: 0 + }, 200, Phaser.Easing.Linear.None); + killTween.onComplete.addOnce(function() { + return brick.kill(); + }, this); + killTween.start(); + score += 10; + scoreText.setText("Points: " + score); + if (score === brickInfo.count.row * brickInfo.count.col * 10) { + alert("A winner is you!"); + location.reload(); + } + return ball.animations.play("wobble"); + }; + + ballHitPaddle = function(ball, paddle) { + ball.animations.play("wobble"); + return ball.body.velocity.x = -1 * 5 * (paddle.x - ball.x); + }; + + preload = function() { + // Set basic game properties + game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; + game.scale.pageAlignHorizontally = true; + game.scale.pageAlignVertically = true; + game.stage.backgroundColor = "#eee"; + // Load texture images + game.load.image("paddle", "img/paddle.png"); + game.load.image("brick", "img/brick.png"); + game.load.spritesheet("ball", "img/wobble.png", 20, 20); + return game.load.spritesheet("button", "img/button.png", 120, 40); + }; + + create = function() { + // Initialize the physics engine + game.physics.startSystem(Phaser.Physics.ARCADE); + game.physics.arcade.checkCollision.down = false; + // Create the ball sprite and set it"s properties + ball = game.add.sprite(game.world.width * 0.5, game.world.height - 25, "ball"); + ball.animations.add("wobble", [0, 1, 0, 2, 0, 1, 0, 2, 0], 24); + ball.anchor.set(0.5); + game.physics.enable(ball, Phaser.Physics.ARCADE); + ball.body.bounce.set(1); + ball.body.collideWorldBounds = true; + ball.checkWorldBounds = true; + ball.events.onOutOfBounds.add(ballLeaveScreen, this); + // Create the paddle sprite and set it"s properties + paddle = game.add.sprite(game.world.width * 0.5, game.world.height - 5, "paddle"); + paddle.anchor.set(0.5, 1); + game.physics.enable(paddle, Phaser.Physics.ARCADE); + paddle.body.immovable = true; + // Brick creation + initBricks(); + // Scorekeeping + scoreText = game.add.text(5, 5, "Points: 0", textStyle); + // Player lives + livesText = game.add.text(game.world.width - 5, 5, "Lives: " + lives, textStyle); + livesText.anchor.set(1, 0); + lifeLostText = game.add.text(game.world.width * 0.5, game.world.height * 0.5, 'Life lost, click to continue', textStyle); + lifeLostText.anchor.set(0.5); + lifeLostText.visible = false; + // Start button + startButton = game.add.button(game.world.width * 0.5, game.world.height * 0.5, "button", startGame, this, 1, 0, 2); + return startButton.anchor.set(0.5); + }; + + update = function() { + game.physics.arcade.collide(ball, paddle, ballHitPaddle); + game.physics.arcade.collide(ball, bricks, ballHitBrick); + if (playing) { + return paddle.x = game.input.x || (game.world.width * 0.5); + } + }; + + functions = { + preload: preload, + create: create, + update: update + }; + + game = new Phaser.Game(480, 320, Phaser.CANVAS, null, functions); + +}).call(this); \ No newline at end of file diff --git a/breakout_phaser.coffee/index.html b/breakout_phaser.coffee/index.html new file mode 100644 index 0000000..3768b97 --- /dev/null +++ b/breakout_phaser.coffee/index.html @@ -0,0 +1,13 @@ + + + + + Gamedev Phaser Workshop - lesson 01: Initialize the framework + + + + + + + + \ No newline at end of file diff --git a/flatten.sh/README.md b/flatten.sh/README.md new file mode 100644 index 0000000..b540ec6 --- /dev/null +++ b/flatten.sh/README.md @@ -0,0 +1 @@ +A Bash script that recursively searches for files in subdirectories of PWD and moves them to PWD. \ No newline at end of file diff --git a/flatten.sh/flatten.sh b/flatten.sh/flatten.sh new file mode 100644 index 0000000..669b43b --- /dev/null +++ b/flatten.sh/flatten.sh @@ -0,0 +1,24 @@ +#! /bin/bash + +BASE_DIR=`pwd` + +for dir in `ls -1 $BASE_DIR` +do + if [[ -d $dir ]] + then + cd $dir + for i in `seq 1 100` + do + FILE=`ls -1` + if [[ -d "$FILE" ]] + then + cd $FILE + else + break + fi + done + mv "$FILE" $BASE_DIR + cd $BASE_DIR + rm -rf $dir + fi +done diff --git a/hello.s/README.md b/hello.s/README.md new file mode 100644 index 0000000..07e3bfe --- /dev/null +++ b/hello.s/README.md @@ -0,0 +1 @@ +Abusing x86_64 assembly language to print Hello, World! \ No newline at end of file diff --git a/hello.s/hello.s b/hello.s/hello.s new file mode 100644 index 0000000..041ab0b --- /dev/null +++ b/hello.s/hello.s @@ -0,0 +1,10 @@ + .section .text + .globl main + .byte 72, 101, 108, 108, 111, 44, 32, 87 + .byte 111, 114, 108, 100, 33, 10, 0 +main: + .quad 0x01c0c748e5894855 + .quad 0xffee358d48000000 + .quad 0xc7480fee8348ffff + .quad 0xc9050f0000000ec2 + .byte 0xc3 \ No newline at end of file diff --git a/pin_fetcher.py/README.md b/pin_fetcher.py/README.md new file mode 100644 index 0000000..e36e57c --- /dev/null +++ b/pin_fetcher.py/README.md @@ -0,0 +1 @@ +A python 3 script that fetches a bunch of images listed as urls on a text file. diff --git a/pin_fetcher.py/pin_fetcher.py b/pin_fetcher.py/pin_fetcher.py new file mode 100644 index 0000000..6aad9d5 --- /dev/null +++ b/pin_fetcher.py/pin_fetcher.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +## +# Specially useful to make backups of your Pinterest boards when used together with +# the pins_from_cache.js script. +## + +import argparse +import requests +import io +import time +from PIL import Image + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description="Download photos from a Pinterest URL list") + parser.add_argument('-u', '--urls', help='The URL list txt file') + parser.add_argument('-d', '--delay', type=int, default=1, help='Delay in seconds between downloads.') + + args = parser.parse_args() + + delay = args.delay + resume = False + target = 0 + + if resume: + with open("log", "r") as log: + target = int(log.readline()) + + with open(args.urls, "r") as f: + line = 0 + for url in f: + + try: + if resume and line < target: + continue + + success = False + url = url.strip() + + # Request the image + print("Fetching: " + url) + req = requests.get(url) + print(req.status_code) + + if req.status_code == 200: + # Save the image to file on success. + img = Image.open(io.BytesIO(req.content)).convert('RGB') + img.save(url.split("/")[-1]) + success = True + + else: + # Attempt to download the image as a PNG on error + url = url.replace(".jpg", ".png") + print("JPG failed") + print("Fetching: " + url) + req = requests.get(url) + print(req.status_code) + + if req.status_code == 200: + # Save the image to file on success. + img = Image.open(io.BytesIO(req.content)) + img.save(url.split("/")[-1]) + success = True + + else: + # Attempt to download the image as a GIF on error + url = url.replace(".png", ".gif") + print("PNG failed") + print("Fetching: " + url) + req = requests.get(url) + print(req.status_code) + + if req.status_code == 200: + # Save the image to file on success. + with open(url.split("/")[-1], "wb") as f: + # Workaround for a PIL bug when saving GIF files + for chunk in req.iter_content(chunk_size=128): + f.write(chunk) + success = True + + elif req.status_code == 403: + # Log the error if JPG, PNG and GIF failed + print("Failed to download: " + url) + + # Log the image if the download was successful + if success: + with open("log", "w") as log: + log.write(str(line)) + + except Exception as e: + print(e) + + line += 1 + + # Wait + time.sleep(delay) \ No newline at end of file diff --git a/pin_fetcher.py/pins_from_cache.js b/pin_fetcher.py/pins_from_cache.js new file mode 100644 index 0000000..af1220d --- /dev/null +++ b/pin_fetcher.py/pins_from_cache.js @@ -0,0 +1,24 @@ +/** + * Script taken and very slightly modified from here: + * https://32hertz.blogspot.com/2015/06/how-to-download-all-pictures-from.html + * + * Open the Firefox cache screen (about:cache, then click on list cache entries on the Disk section), + * then run this script on the Firefox console to get all links for Pinterest images that you have seen. + * Copy all the links in a .txt file and you can use img_spider.py to download them all. + **/ +var a = document.getElementsByTagName("a"); +var img; +var i = -1; +var body = document.getElementsByTagName("body"); +var div = document.createElement("div"); +var jpglink=''; + +while(++i0){ + jpglink = document.createTextNode(a[i].innerHTML.replace("236x","originals")); + div.appendChild(jpglink); + div.appendChild(document.createElement("br")); + } +} + +body[0].insertBefore(div,body[0].childNodes[0]); \ No newline at end of file diff --git a/print_all_images.sh/README.md b/print_all_images.sh/README.md new file mode 100644 index 0000000..c3eb029 --- /dev/null +++ b/print_all_images.sh/README.md @@ -0,0 +1 @@ +Bash script that prints all JPEG and PNG images inside the working directory. \ No newline at end of file diff --git a/print_all_images.sh/print_all_images.sh b/print_all_images.sh/print_all_images.sh new file mode 100644 index 0000000..b166812 --- /dev/null +++ b/print_all_images.sh/print_all_images.sh @@ -0,0 +1,19 @@ +#! /bin/bash + +FILES=`ls -1 *.[jp]*` +ORIENTATION=" " + +for f in $FILES +do + WIDTH=`identify $f | cut -d' ' -f3 | cut -d'x' -f1` + HEIGHT=`identify $f | cut -d' ' -f3 | cut -d'x' -f2` + if [ $WIDTH -lt $HEIGHT ] + then + ORIENTATION="portrait" + else + ORIENTATION="landscape" + fi + echo "Printing $f" + echo + lpr -o $ORIENTATION -o scaling=100 -o media=letter -o color=grayscale -o PrintQuality=photo $f +done diff --git a/qs.coffee/README.md b/qs.coffee/README.md new file mode 100644 index 0000000..b7ff877 --- /dev/null +++ b/qs.coffee/README.md @@ -0,0 +1 @@ +Quicksort implementation in Coffeescript for practice. \ No newline at end of file diff --git a/qs.coffee/qs.coffee b/qs.coffee/qs.coffee new file mode 100644 index 0000000..2def557 --- /dev/null +++ b/qs.coffee/qs.coffee @@ -0,0 +1,13 @@ +#! /usr/bin/env coffee + +test = [20, 16, 5, 10, 3, 17, 12, 1, 19, 6, 13, 4, 18, 11, 7, 9, 8, 16, 0, 2, 14, 15] + +quicksort = (list) -> + return [] if list.length == 0 + return list if list.length == 1 + pvt = list.shift() + ltp = (elem for elem in list when elem < pvt) + gtp = (elem for elem in list when elem >= pvt) + return (quicksort ltp).concat [pvt], quicksort gtp + +console.log quicksort test diff --git a/smash.s/README.md b/smash.s/README.md new file mode 100644 index 0000000..dce8619 --- /dev/null +++ b/smash.s/README.md @@ -0,0 +1 @@ +Smashing the stack for fun and no profit. \ No newline at end of file diff --git a/smash.s/smash.s b/smash.s/smash.s new file mode 100644 index 0000000..88e1141 --- /dev/null +++ b/smash.s/smash.s @@ -0,0 +1,28 @@ + .section .rodata +str: + .asciz "Smashed!" + + .section .text + .globl main +main: + pushq %rbp + movq %rsp, %rbp + call function + xorl %eax, %eax + leave + ret + +function: + pushq %rbp + movq %rsp, %rbp + leaq smash(%rip), %r8 + movq %r8, 8(%rbp) + leave + ret + +smash: + leaq str(%rip), %rdi + call puts@plt + movq $60, %rax + movq $89, %rdi + syscall \ No newline at end of file