Skip to content

Commit

Permalink
feat: Integrate Arcadian headpieces
Browse files Browse the repository at this point in the history
  • Loading branch information
johnedvard committed Aug 22, 2022
1 parent 343a0e0 commit 6843b19
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 5 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"description": "skeleton rope physics game",
"source": "src/index.html",
"scripts": {
"start": "parcel serve",
"build": "rm -rf dist && parcel build src/index.html",
"start": "parcel serve --no-cache",
"build": "rm -rf dist && parcel build --no-cache src/index.html",
"zip": "cd dist && zip game.zip *.png *.html *.css *.js static/level/*.json",
"build:zip": "npm run build && cd dist && zip game.zip *.png *.html *.css *.js static/level/*.json",
"build:roadroller": "npm run build && roadroller dist/index.*.js -o dist/index.*.js && npm run zip",
Expand Down
42 changes: 40 additions & 2 deletions src/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@ import { getPointer, Sprite, on } from 'kontra';
import { PlayerControls } from './PlayerControls';
import { PointMass } from './PointMass';
import { fgc2, RESTING_DISTANCE } from './constants';
import { GOAL_COLLISION } from './gameEvents';
import { ARCADIAN_ADDED, GOAL_COLLISION } from './gameEvents';

export class Player {
game;
rope = []; // list of pointmasses
pointMass; // used to attach to the end of the rope
playerControls;
sprite = { render: () => {}, x: 0, y: 0 }; // draw sprite on pointmass position
scale = 4;
sprite = { render: () => {}, x: 0, y: 0 }; // draw sprite on pointmass position
headSprite = { render: () => {}, x: 0, y: 0 }; // From Arcadian API
hasWon = false;
headImg = { width: 0, height: 0 };
headOffset = { x: 10, y: 38 };
isLeft = false;

constructor({ game, levelData }) {
this.game = game;
Expand Down Expand Up @@ -64,6 +68,21 @@ export class Player {
});
};
}
createHeadSprite(img) {
const scale = this.scale / 2;
let scaleX = scale;
if (this.isLeft) scaleX = scaleX * -1;
this.headSprite = Sprite({
x: this.pointMass.x - img.width,
y: this.pointMass.y - img.height,
anchor: { x: 0.5, y: 0.5 },
width: 8,
height: 8,
image: img,
scaleX: scaleX,
scaleY: scale,
});
}

createRope({ startX, startY, ropeLength }) {
const anchor = new PointMass(startX, startY, {
Expand Down Expand Up @@ -95,18 +114,26 @@ export class Player {

renderPlayer(_ctx) {
this.sprite.render();
this.headSprite.render();
}

applyForce(fX, fY) {
this.pointMass.applyForce(fX, fY);
}

changePlayerDirection(isLeft) {
this.isLeft = isLeft;
if (isLeft) {
this.sprite.scaleX = -this.scale;
this.headSprite.scaleX = -this.scale / 2;
} else {
this.sprite.scaleX = this.scale;
this.headSprite.scaleX = this.scale / 2;
}
// prevent headpiece from flashing
this.headSprite.x =
this.sprite.x -
(this.headImg.width - this.headOffset.x) * Math.sign(this.sprite.scaleX);
}

render(ctx) {
Expand All @@ -131,6 +158,12 @@ export class Player {
update() {
this.sprite.x = this.pointMass.x;
this.sprite.y = this.pointMass.y;
this.headSprite.x =
this.pointMass.x -
(this.headImg.width - this.headOffset.x) * Math.sign(this.sprite.scaleX);

this.headSprite.y =
this.pointMass.y - this.headImg.height + +this.headOffset.y;

this.updateRope();
this.dragRope(); // TODO (johnedvard) Only enable in local and beta env
Expand Down Expand Up @@ -162,8 +195,13 @@ export class Player {

listenForGameEvents() {
on(GOAL_COLLISION, this.onGoalCollision);
on(ARCADIAN_ADDED, this.onArcadianAdded);
}
onGoalCollision = () => {
this.hasWon = true;
};
onArcadianAdded = ({ img }) => {
this.headImg = img;
this.createHeadSprite(img);
};
}
44 changes: 44 additions & 0 deletions src/arcadianApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
export const arcadianHeadImages = [];

export async function queryArcadian(id) {
const partsUrl =
'https://nftstorage.link/ipfs/bafybeib2ir3zpgd3cmizcv7shekjeftcwq7apjib6i5gz2sjc4vajwtgiy';

// this is the same url that you get from querying token uri from the contract
const url = 'https://api.arcadians.io/' + id;

return new Promise((resolve, reject) => {
// create a GET request
var xhr = new XMLHttpRequest();
xhr.onload = () => {
if (xhr.readyState === xhr.DONE) {
if (xhr.status !== 200) reject(null);
let gender = 'female';
var data = JSON.parse(xhr.response);
console.log('data', data);

const headPart = data.attributes.find(
(trait) => trait.trait_type === 'Head'
);
const genderPart = data.attributes.find(
(trait) => trait.trait_type === 'Class'
);
if (genderPart.value.match('Male')) gender = 'male';
const headUrl = headPart.value.toLowerCase().replaceAll(' ', '-');
var img = new Image();
img.src = `${partsUrl}/${gender}/head/${headUrl}.png`;
img.addEventListener(
'load',
() => {
localStorage.setItem('Arcadian #' + id, xhr.response);
arcadianHeadImages.push(img);
resolve(img);
},
false
);
}
};
xhr.open('GET', url);
xhr.send();
});
}
Binary file added src/assets/img/heart.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/gameEvents.js
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const GOAL_COLLISION = 'gc';
export const ARCADIAN_ADDED = 'aa';
19 changes: 18 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { emit } from 'kontra';

import { Game } from './Game';
import { NearConnection } from './near/nearConnection';
import { ARCADIAN_ADDED } from './gameEvents';
import { queryArcadian } from './arcadianApi';
import { initLoginLogout } from './near/nearLogin';
import { NearConnection } from './near/nearConnection';

const init = () => {
new Game();
initNear();
fetchArcadianHeads();
};

const initNear = () => {
Expand All @@ -26,4 +32,15 @@ const loadNearApi = () => {
document.head.appendChild(script);
});
};

const fetchArcadianHeads = () => {
// TODO (johnedvard) get from localStorage so we don't call the api too much
// get many headpices
for (let i = 0; i < 60; i += 5)
queryArcadian(i).then((img) => {
if (img) {
emit(ARCADIAN_ADDED, { img });
}
});
};
init();
1 change: 1 addition & 0 deletions src/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

0 comments on commit 6843b19

Please sign in to comment.