NEMTUSハッカソンに向けて
プログラム超初心者達が
Symbolを取り入れた簡単なゲームを開発するお話。
『~Challenge SymbolEnjoneer~』
一緒に見ていきましょう!Let’s Enjoy!
part.7
こんにちは!サカショウです🐶
前回パートでは、スロットゲームとブロック崩しゲームを作成しSymbolを実装しました!
今回は、前回作ったブロック崩しゲームを改造して、別のステージを2つ完成させましょう✨
それでは、僕と一緒に進めていきましょう。
※本連載記事に記載の内容は、テストネットのみの利用にとどめてください。 そのままメインネットに使用する事は、できません。 秘密鍵が公開されてしまいますので、絶対にメインネットで使用しないと約束してください。
【今回パートに必要なもの】
- PC(サカショウの環境は、Windows10)
- インターネット環境
- Symbol Desktop Wallet V1.0.9(テストネット)
- テストネットアカウント×2
- ブラウザ(Google chrome)(サカショウは、BraveのGoogleブラウザ)
- VSCode
()内は、サカショウの環境です。異なる環境の場合、異なる挙動を取る可能性があります。
【使用するツールとライブラリ】
- xembook / nem2-browserify / symbol-sdk-1.0.1.js
- FAUCET
- エクスプローラー
【 サカショウ Hack+Version】 ブロック崩しV2
※前回パートで作成したブロック崩しV1のファイルを複製して開いてください。
var要素とStyleタグの変数を少し変更します!
<head>
<meta charset="utf-8" />
<title>ブロック崩しv2</title>
//backgroundを' #000 'に変更する。
<style>
* { padding: 20; margin: 20; }
canvas { background: #eee; display: block; margin: 0 auto;
</style>
</head>
まずは、3行目~10行目辺りにあるStyleを変更して、ゲーム背景を黒色にします。
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 10;
var x = canvas.width/2;
var y = canvas.height-30;
var dx = 2;
var dy = -2;
var paddleHeight = 10;
//paddleWidthを' 70 'に変更して、少しパドル幅を狭めます。
var paddleWidth = 75;
var paddleX = (canvas.width-paddleWidth)/2;
var rightPressed = false;
var leftPressed = false;
//brickRowCountとbrickColumnCountを' 6 'と' 5 'に変更して、ブロックの行と列を変更します。
var brickRowCount = 6;
var brickColumnCount = 5;
var brickWidth = 75;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var score = 0;
var lives = 1;
25行目~45行目辺りにある上記のvar要素を、
//以降に書いてある指示に従い、必要事項を変更する。
【答え合わせ】
- 0000000….の羅列記載箇所を、送金するアカウントの秘密鍵に変更する。
- aaaaaaa…..の羅列記載箇所を、XYMを受け取るアカウントのアドレスに変更する。
上記2か所を自分のアカウント情報に変更することで、ブロック崩しV2が遊べます🐶✨
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>ブロック崩しv2</title>
<style>
* { padding: 20; margin: 20; }
canvas { background: #000; display: block; margin: 0 auto;
</style>
</head>
<body>
<canvas id="myCanvas" width="480" height="320"></canvas>
<script src="https://xembook.github.io/nem2-browserify/symbol-sdk-1.0.1.js"></script>
<script language="JavaScript">
NODE = 'https://sym-test-07.opening-line.jp:3001';
GENERATION_HASH = '7FCCD304802016BEBBCD342A332F91FF1F3BB5E902988B352697BE245F48E836';
EPOCH_ADJUSTMENT = 1637848847;
nem = require("/node_modules/symbol-sdk");
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 10;
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var paddleHeight = 10;
var paddleWidth = 70;
var paddleX = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 5;
var brickColumnCount = 3;
var brickWidth = 75;
var brickHeight = 20;
var brickPadding = 10;
var brickOffsetTop = 30;
var brickOffsetLeft = 30;
var score = 0;
var lives = 1;
var bricks = [];
for(var c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for(var r = 0; r < brickRowCount; r++) {
bricks[c][r] = {x: 0, y: 0, status: 1};
}
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
function keyDownHandler(e) {
if(e.key == "Right" || e.key == "ArrowRight") {
rightPressed = true;
}
else if(e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = true;
}
}
function keyUpHandler(e) {
if(e.key == "Right" || e.key == "ArrowRight") {
rightPressed = false;
}
else if(e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = false;
}
}
function mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if(relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
function collisionDetection() {
for(var c = 0; c < brickColumnCount; c++) {
for(var r = 0; r < brickRowCount; r++) {
var b = bricks[c][r];
if(b.status == 1) {
if(x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
dy = -dy;
b.status = 0;
score++;
if(score == brickRowCount * brickColumnCount) {
alert("YOU WIN, CONGRATULATIONS!");
alice = nem.Account.createFromPrivateKey('000000000000000000000000000000000000000000000000000000000000000',
nem.NetworkType.TEST_NET);
console.log(alice);
tx = nem.TransferTransaction.create(
nem.Deadline.create(EPOCH_ADJUSTMENT),
nem.Address.createFromRawAddress("aaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
[new nem.Mosaic(new nem.MosaicId('3A8416DB2D53B6C8'), nem.UInt64.fromUint(1000000))],
nem.PlainMessage.create('NEMTUS Hackathon Hack+2022 ブロック崩しv2 Clear!'),
nem.NetworkType.TEST_NET,
nem.UInt64.fromUint(100000)
);
console.log(tx);
signedTx = alice.sign(tx, GENERATION_HASH);
console.log(signedTx);
new nem.TransactionHttp(NODE)
.announce(signedTx)
.subscribe((x) => console.log(x), (err) => console.error(err));
alert("Reload");
document.location.reload();
}
}
}
}
}
}
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function drawBricks() {
for(var c = 0; c < brickColumnCount; c++) {
for(var r = 0; r < brickRowCount; r++) {
if(bricks[c][r].status == 1) {
var brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
var brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
}
}
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillStyle = "#0095DD";
ctx.fillText("Score:" + score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillStyle = "#0095DD";
ctx.fillText("Lives:" + lives, canvas.width - 65, 20);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
drawBricks();
drawPaddle();
drawScore();
drawLives();
collisionDetection();
if(x + dx > canvas.width - ballRadius | x + dx < ballRadius) {
dx = -dx;
}
if(y + dy < ballRadius) {
dy = -dy;
} else if(y + dy > canvas.height - ballRadius) {
if(x > paddleX && x < paddleX + paddleWidth) {
dy = -dy;
}
else {
lives--;
if(!lives) {
alert("GAME OVER");
document.location.reload();
}
else {
x = canvas.width / 2;
y = canvas.height - 30;
dx = 3;
dy = -3;
paddleX = (canvas.width - paddleWidth) / 2;
}
}
}
if(rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
}
else if(leftPressed && paddleX > 0) {
paddleX -= 7;
}
x += dx;
y += dy;
requestAnimationFrame(draw);
}
draw();
</script>
</body>
</html>
【 サカショウ Hack+Version】 ブロック崩しV3
ブロック崩しV2のどこを変えればブロック崩しV3になるのかな?
行った変更点は、ブロックのサイズと設置個数変更、余白調整とカラー変更、パドルに反発する度にボールを加速させる。これらを追加変更しています😋
コードを見比べて、読解力を鍛えてみよう!🐶✨
- 0000000….の羅列記載箇所を、送金するアカウントの秘密鍵に変更する。
- aaaaaaa…..の羅列記載箇所を、XYMを受け取るアカウントのアドレスに変更する。
上記2か所を自分のアカウント情報に変更することで、ブロック崩しV3が遊べます🐶✨
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>ブロック崩しv3</title>
<style>
* { padding: 20; margin: 20; }
canvas { background: #000; display: block; margin: 0 auto;
</style>
</head>
<body>
<canvas id="myCanvas" width="480" height="320"></canvas>
<script src="https://xembook.github.io/nem2-browserify/symbol-sdk-1.0.1.js"></script>
<script language="JavaScript">
NODE = 'https://sym-test-07.opening-line.jp:3001';
GENERATION_HASH = '7FCCD304802016BEBBCD342A332F91FF1F3BB5E902988B352697BE245F48E836';
EPOCH_ADJUSTMENT = 1637848847;
nem = require("/node_modules/symbol-sdk");
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var ballRadius = 12;
var x = canvas.width / 2;
var y = canvas.height - 30;
var dx = 2;
var dy = -2;
var paddleHeight = 10;
var paddleWidth = 70;
var paddleX = (canvas.width - paddleWidth) / 2;
var rightPressed = false;
var leftPressed = false;
var brickRowCount = 5;
var brickColumnCount = 10;
var brickWidth = 38;
var brickHeight = 30;
var brickPadding = 7;
var brickOffsetTop = 20;
var brickOffsetLeft = 20;
var bricks = [];
var score = 0;
var lives = 3;
var bricks = [];
for(var c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for(var r = 0; r < brickRowCount; r++) {
bricks[c][r] = {x: 0, y: 0, status: 1};
}
}
function collisionDetection() {
for(var c = 0; c < brickColumnCount; c++) {
for(var r = 0; r < brickRowCount; r++) {
var b = bricks[c][r];
if(b.status == 1) {
if(x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
dy = -dy;
b.status = 0;
score++;
if(score == brickRowCount * brickColumnCount) {
alert("YOU WIN, CONGRATULATIONS!");
alice = nem.Account.createFromPrivateKey('0000000000000000000000000000000000000000000000000000',
nem.NetworkType.TEST_NET);
console.log(alice);
tx = nem.TransferTransaction.create(
nem.Deadline.create(EPOCH_ADJUSTMENT),
nem.Address.createFromRawAddress('aaaaaaaaaaaaaaaaaaaaaaaaaaaa'),
[new nem.Mosaic(new nem.MosaicId('3A8416DB2D53B6C8'), nem.UInt64.fromUint(1000000))],
nem.PlainMessage.create('NEMTUS Hackathon Hack+2022 ブロック崩しv3 Clear!'),
nem.NetworkType.TEST_NET,
nem.UInt64.fromUint(100000)
);
console.log(tx);
signedTx = alice.sign(tx, GENERATION_HASH);
console.log(signedTx);
new nem.TransactionHttp(NODE)
.announce(signedTx)
.subscribe((x) => console.log(x), (err) => console.error(err));
alert("Reload");
document.location.reload();
}
}
}
}
}
}
function drawScore() {
ctx.font = "16px Arial";
ctx.fillStyle = "#ffa500";
ctx.fillText("Score:" + score, 8, 20);
}
function drawLives() {
ctx.font = "16px Arial";
ctx.fillStyle = "#ffa500";
ctx.fillText("Lives:" + lives, canvas.width - 65, 20);
}
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
ctx.fillStyle = "#faebd7";
ctx.fill();
ctx.closePath();
}
function drawBricks() {
for(var c = 0; c < brickColumnCount; c++) {
for(var r = 0; r < brickRowCount; r++) {
if(bricks[c][r].status == 1) {
var brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
var brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fillStyle = "#ffd700";
ctx.fill();
ctx.closePath();
}
}
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBall();
drawBricks();
drawPaddle();
drawScore();
drawLives();
collisionDetection();
if(x + dx > canvas.width - ballRadius | x + dx < ballRadius) {
dx = -dx;
}
if(y + dy < ballRadius) {
dy = -dy;
} else if(y + dy > canvas.height - ballRadius) {
if(x > paddleX && x < paddleX + paddleWidth) {
dy = -dy*1.1;
}
else {
lives--;
if(!lives) {
alert("GAME OVER");
document.location.reload();
}
else {
x = canvas.width / 2;
y = canvas.height - 30;
dx = 2;
dy = -2;
// dx = 5;
// dy = -5;
paddleX = (canvas.width - paddleWidth) / 2;
}
}
}
if(rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
}
else if(leftPressed && paddleX > 0) {
paddleX -= 7;
}
x += dx;
y += dy;
requestAnimationFrame(draw);
}
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
function keyDownHandler(e) {
if(e.key == "Right" || e.key == "ArrowRight") {
rightPressed = true;
}
else if(e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = true;
}
}
function keyUpHandler(e) {
if(e.key == "Right" || e.key == "ArrowRight") {
rightPressed = false;
}
else if(e.key == "Left" || e.key == "ArrowLeft") {
leftPressed = false;
}
}
function mouseMoveHandler(e) {
var relativeX = e.clientX - canvas.offsetLeft;
if(relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
draw();
</script>
</body>
</html>
いかがでしたか?
さあ、もうすぐハッカタスの締切だ!!僕ももう行かなくちゃッ!!
NEMTUS Hackathon Hack+2022でのプログラミング入門チャレンジは、ここまでです🐶✨
最後までチャレンジしてくださった皆様!!ありがとうございました!!!!
最高のSymbol Lifeが皆様に訪れ続けますように。