health bar and refactor
This commit is contained in:
parent
0f042d89eb
commit
3ad8f55829
26
index.html
26
index.html
|
@ -2,25 +2,29 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Adventures with Anxiety!</title>
|
||||
<link rel="stylesheet" type="text/css" href="game.css">
|
||||
<link rel="stylesheet" type="text/css" href="styles/game.css">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="game_container">
|
||||
<canvas id="game_canvas"></canvas>
|
||||
<div id="game_words">
|
||||
</div>
|
||||
<div id="game_hp">
|
||||
<div id="hp_human"></div>
|
||||
<div id="hp_wolf"></div>
|
||||
</div>
|
||||
<div id="game_choices">
|
||||
</div>
|
||||
<div id="game_words" class="no_select"></div>
|
||||
<div id="game_hp"></div>
|
||||
<div id="game_choices" class="no_select"></div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script src="pinkyswear.min.js"></script>
|
||||
<script src="game.js"></script>
|
||||
<!-- SCRIPTS -->
|
||||
<script src="scripts/lib/pinkyswear.min.js"></script>
|
||||
<script src="scripts/lib/minpubsub.min.js"></script>
|
||||
|
||||
<script src="scripts/game/Game.js"></script>
|
||||
<script src="scripts/game/Sprite.js"></script>
|
||||
<script src="scripts/game/Beebee.js"></script>
|
||||
<script src="scripts/game/HP.js"></script>
|
||||
<script src="scripts/game/SceneSetup.js"></script>
|
||||
|
||||
<script src="scripts/main.js"></script>
|
|
@ -0,0 +1,47 @@
|
|||
# demo
|
||||
|
||||
`SceneSetup.demo()`
|
||||
|
||||
> Prepare for trouble!
|
||||
|
||||
Oh no!
|
||||
|
||||
(#demo-attacks)
|
||||
|
||||
# demo-attacks
|
||||
|
||||
[Attack 10 points](#demo-attack-low)
|
||||
|
||||
[Attack 20 points](#demo-attack-med)
|
||||
|
||||
[Attack 50%](#demo-attack-hi)
|
||||
|
||||
# demo-attack-low
|
||||
|
||||
`HP.attackHong("10p")`
|
||||
|
||||
{{if HP.hong==0}} (#dead) {{/if}}
|
||||
|
||||
(#demo-attacks)
|
||||
|
||||
# demo-attack-med
|
||||
|
||||
`HP.attackHong("20p")`
|
||||
|
||||
{{if HP.hong==0}} (#dead) {{/if}}
|
||||
|
||||
(#demo-attacks)
|
||||
|
||||
# demo-attack-hi
|
||||
|
||||
`HP.attackHong("50%")`
|
||||
|
||||
{{if HP.hong==0}} (#dead) {{/if}}
|
||||
|
||||
(#demo-attacks)
|
||||
|
||||
# dead
|
||||
|
||||
i am ded
|
||||
|
||||
> u r ded
|
|
@ -1,6 +1,9 @@
|
|||
# woods
|
||||
|
||||
`document.body.style.background = "#ddd"`
|
||||
```
|
||||
document.body.style.background = "#ddd"
|
||||
publish("beebee", ["normal"])
|
||||
```
|
||||
|
||||
Two roads diverged in the woods and I...
|
||||
{{if _.eaten}} (this time try not to get eaten by wolves) {{/if}}
|
||||
|
@ -13,11 +16,14 @@ Two roads diverged in the woods and I...
|
|||
|
||||
# woods-less
|
||||
|
||||
`document.body.style.background = "#ff4040"`
|
||||
|
||||
And that's how I got lost in the woods and was eaten by wolves
|
||||
{{if _.eaten}} (...again.) {{/if}}
|
||||
|
||||
```
|
||||
document.body.style.background = "#ff4040"
|
||||
publish("beebee", ["panic"])
|
||||
```
|
||||
|
||||
`_.eaten = true`
|
||||
|
||||
`_.played_less = true`
|
||||
|
@ -38,6 +44,8 @@ And that's how I found my way back to civilization and was not eaten by wolves
|
|||
|
||||
Good choice.
|
||||
|
||||
`publish("beebee", ["yay"])`
|
||||
|
||||
(#END)
|
||||
|
||||
do NOT show this line
|
|
@ -0,0 +1,54 @@
|
|||
function Beebee(){
|
||||
|
||||
var self = this;
|
||||
|
||||
// Sprite!
|
||||
var beebeeImage = new Image();
|
||||
beebeeImage.src = "sprites/beebee.png";
|
||||
self.sprite = new Sprite({
|
||||
image: beebeeImage,
|
||||
grid:{
|
||||
width: 1,
|
||||
height: 2
|
||||
},
|
||||
frame:{
|
||||
width: 720,
|
||||
height: 500
|
||||
},
|
||||
anchor:{
|
||||
x: 300,
|
||||
y: 230
|
||||
},
|
||||
frameNames:[
|
||||
"normal",
|
||||
"panic",
|
||||
"yay"
|
||||
],
|
||||
x: 300,
|
||||
y: 430,
|
||||
rotation: 0,
|
||||
scale: 1,
|
||||
squash: 1
|
||||
});
|
||||
|
||||
// Draw
|
||||
var ticker = 1;
|
||||
self.draw = function(ctx){
|
||||
|
||||
// Bouncing based on frame!
|
||||
ticker += 1/20;
|
||||
if(self.sprite.currentFrameName == "panic"){
|
||||
ticker += 1;
|
||||
}
|
||||
self.sprite.squash = 1 + Math.sin(ticker)*0.05;
|
||||
|
||||
// Draw me!
|
||||
self.sprite.draw(ctx);
|
||||
|
||||
};
|
||||
|
||||
subscribe("beebee", function(frameName){
|
||||
self.sprite.gotoFrameByName(frameName);
|
||||
});
|
||||
|
||||
}
|
|
@ -1,16 +1,3 @@
|
|||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'woods.md?v='+Math.random());
|
||||
xhr.onload = function() {
|
||||
if(xhr.status===200){
|
||||
Game.onload(xhr.responseText);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
|
||||
/*****************************/
|
||||
/*****************************/
|
||||
/*****************************/
|
||||
|
||||
window._ = {};
|
||||
window.Game = {};
|
||||
|
||||
|
@ -69,21 +56,19 @@ Game.onload = function(data){
|
|||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SCENE MANAGEMENT ////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Game.start = function(){
|
||||
window._ = {}; // global var, reset
|
||||
Game.goto(Game.startSectionID);
|
||||
};
|
||||
|
||||
Game.update = function(){
|
||||
|
||||
var wordsHeight = 80 + Game.wordsDOM.getBoundingClientRect().height;
|
||||
var currentY = parseFloat(Game.wordsDOM.style.top) || 80;
|
||||
var gotoY = (wordsHeight<260) ? 0 : wordsHeight-260;
|
||||
gotoY = 80 - gotoY;
|
||||
|
||||
var nextY = currentY*0.9 + gotoY*0.1;
|
||||
Game.wordsDOM.style.top = nextY+"px";
|
||||
|
||||
Game.updateText();
|
||||
Game.updateCanvas();
|
||||
publish("update");
|
||||
};
|
||||
|
||||
Game.goto = function(sectionID){
|
||||
|
@ -101,9 +86,8 @@ Game.goto = function(sectionID){
|
|||
Game.executeNextLine();
|
||||
|
||||
};
|
||||
Game.executeNextLine = function(){
|
||||
|
||||
var doNextLineImmediately = false;
|
||||
Game.executeNextLine = function(){
|
||||
|
||||
// Parse handlebars
|
||||
var originalLine = Game.queue.shift();
|
||||
|
@ -112,7 +96,11 @@ Game.executeNextLine = function(){
|
|||
|
||||
// Execute line
|
||||
var promiseNext;
|
||||
if(line!=""){ // none, don't execute...
|
||||
if(line==""){
|
||||
// If no line, get immediate promise...
|
||||
promiseNext = new pinkySwear();
|
||||
promiseNext(true, []);
|
||||
}else{
|
||||
|
||||
// Execute based on what type it is!
|
||||
var lineType = Game.getLineType(line);
|
||||
|
@ -122,11 +110,9 @@ Game.executeNextLine = function(){
|
|||
break;
|
||||
case "choice":
|
||||
promiseNext = Game.executeChoice(line);
|
||||
doNextLineImmediately = true;
|
||||
break;
|
||||
case "code":
|
||||
promiseNext = Game.executeCode(line);
|
||||
doNextLineImmediately = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -154,6 +140,21 @@ Game.addToQueue = function(line){
|
|||
Game.queue.push(line);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// TEXT AND STUFF //////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Move the text DOM to latest
|
||||
Game.updateText = function(){
|
||||
var wordsHeight = 80 + Game.wordsDOM.getBoundingClientRect().height;
|
||||
var currentY = parseFloat(Game.wordsDOM.style.top) || 80;
|
||||
var gotoY = (wordsHeight<260) ? 0 : wordsHeight-260;
|
||||
gotoY = 80 - gotoY;
|
||||
var nextY = currentY*0.9 + gotoY*0.1;
|
||||
Game.wordsDOM.style.top = nextY+"px";
|
||||
};
|
||||
|
||||
// Execute text! Just add it to text DOM.
|
||||
Game.executeText = function(line){
|
||||
|
||||
|
@ -325,15 +326,45 @@ Game.parseLine = function(line){
|
|||
|
||||
};
|
||||
|
||||
|
||||
/*****************************/
|
||||
/*****************************/
|
||||
/*****************************/
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// WHERE STUFF WILL BE DRAWN ///////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Game.canvas = document.querySelector("#game_canvas");
|
||||
Game.canvas.width = 360 * 2;
|
||||
Game.canvas.height = 450 * 2;
|
||||
Game.canvas.style.width = Game.canvas.width/2 + "px";
|
||||
Game.canvas.style.height = Game.canvas.height/2 + "px";
|
||||
Game.context = Game.canvas.getContext("2d");
|
||||
|
||||
// A blank scene
|
||||
Game.resetScene = function(){
|
||||
Game.scene = {};
|
||||
Game.scene.children = [];
|
||||
};
|
||||
Game.resetScene();
|
||||
|
||||
// Update & draw all the kids!
|
||||
Game.updateCanvas = function(){
|
||||
|
||||
// For retina
|
||||
var ctx = Game.context;
|
||||
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
|
||||
ctx.save();
|
||||
ctx.scale(2,2);
|
||||
|
||||
// Update/Draw all kids
|
||||
Game.scene.children.forEach(function(child){
|
||||
child.draw(ctx);
|
||||
});
|
||||
|
||||
// Restore
|
||||
ctx.restore();
|
||||
|
||||
// Draw HP
|
||||
HP.draw();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
// Singleton - it's always there!
|
||||
window.HP = new HitPoints();
|
||||
|
||||
// The Class!
|
||||
function HitPoints(){
|
||||
|
||||
var self = this;
|
||||
|
||||
// My DOM & canvas
|
||||
self.dom = document.querySelector("#game_hp");
|
||||
self.canvas = document.createElement("canvas");
|
||||
self.canvas.width = 360 * 2;
|
||||
self.canvas.height = 70 * 2;
|
||||
self.canvas.style.width = self.canvas.width/2 + "px";
|
||||
self.canvas.style.height = self.canvas.height/2 + "px";
|
||||
self.context = self.canvas.getContext("2d");
|
||||
self.dom.appendChild(self.canvas);
|
||||
|
||||
// My sprite
|
||||
self.image = new Image();
|
||||
self.image.src = "sprites/hp.png";
|
||||
|
||||
// My stats
|
||||
self.reset = function(){
|
||||
self.hong = 100;
|
||||
self.beebee = 100;
|
||||
};
|
||||
self.reset();
|
||||
|
||||
// Attack!
|
||||
self.doDamage = function(str, target){
|
||||
|
||||
// Absolute or Relative Damage?
|
||||
var num = parseFloat(str);
|
||||
var isAbsolute = (str.slice(-1)=="p"); // p = absolute, % = relative
|
||||
if(isAbsolute){
|
||||
self[target] -= num;
|
||||
}else{
|
||||
var relativeDamage = Math.floor( self[target] * (num/100) );
|
||||
self[target] -= relativeDamage;
|
||||
}
|
||||
|
||||
// Floor bound
|
||||
if(self[target]<0){
|
||||
self[target] = 0;
|
||||
}
|
||||
|
||||
};
|
||||
// TODO: SHAKING BASED ON AMOUNT OF ABSOLUTE DAMAGE.
|
||||
self.attackHong = function(str){
|
||||
self.doDamage(str, "hong");
|
||||
self.leftShake = 30;
|
||||
};
|
||||
self.attackBeebee = function(str){
|
||||
self.doDamage(str, "beebee");
|
||||
self.rightShake = 30;
|
||||
};
|
||||
|
||||
// Draw
|
||||
self.leftShake = 0;
|
||||
self.leftWidth = 360;
|
||||
self.rightShake = 0;
|
||||
self.rightWidth = 360;
|
||||
self.drawHalf = function(ctx, isRight){
|
||||
|
||||
ctx.save();
|
||||
|
||||
// Which side?
|
||||
var side = isRight ? "right" : "left";
|
||||
var hp = isRight ? self.beebee : self.hong;
|
||||
|
||||
// Shaking
|
||||
if(self[side+"Shake"]>0){
|
||||
var amp = self[side+"Shake"]/7;
|
||||
var shakeY = Math.sin(self[side+"Shake"]*1.3)*amp;
|
||||
ctx.translate(0,shakeY);
|
||||
self[side+"Shake"]--;
|
||||
}else{
|
||||
self[side+"Shake"]=0;
|
||||
}
|
||||
|
||||
// BLACK
|
||||
var sx=isRight ? 360 : 0, sy=0, sw=360, sh=150;
|
||||
ctx.drawImage(self.image, sx,sy,sw,sh, sx/2,sy/2,sw/2,sh/2); // black
|
||||
|
||||
// RED
|
||||
var hpRatio = (hp+32)/(100+32); // 100,0 => 1,0.3
|
||||
sw = 360 * hpRatio;
|
||||
sy = 150;
|
||||
self[side+"Width"] = self[side+"Width"]*0.8 + sw*0.2;
|
||||
sw = self[side+"Width"];
|
||||
if(sw>88){
|
||||
if(isRight){
|
||||
ctx.drawImage(self.image, sx+(360-sw),sy,sw,sh, 360/2,0,sw/2,sh/2);
|
||||
}else{
|
||||
ctx.drawImage(self.image, sx,sy,sw,sh, (360-sw)/2,0,sw/2,sh/2);
|
||||
}
|
||||
}
|
||||
if(self[side+"WhiteWidth"]>sw && self[side+"Shake"]<=0){
|
||||
self[side+"WhiteWidth"] -= 0.6;
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
|
||||
};
|
||||
self.draw = function(){
|
||||
|
||||
var ctx = self.context;
|
||||
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
|
||||
ctx.save();
|
||||
ctx.scale(2,2);
|
||||
|
||||
// Draw Left & Right Sides
|
||||
self.drawHalf(ctx, false);
|
||||
self.drawHalf(ctx, true);
|
||||
|
||||
// Draw "Timer"
|
||||
var sx=0, sy=450, sw=720, sh=150;
|
||||
ctx.drawImage(self.image, sx,sy,sw,sh, 0,0,sw/2,sh/2);
|
||||
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/**********************************
|
||||
|
||||
A big ol' singleton class that just makes it easy to create scenes.
|
||||
|
||||
**********************************/
|
||||
|
||||
window.SceneSetup = {};
|
||||
|
||||
SceneSetup.demo = function(){
|
||||
|
||||
Game.resetScene();
|
||||
|
||||
var beebee = new Beebee();
|
||||
Game.scene.children.push(beebee);
|
||||
|
||||
};
|
|
@ -0,0 +1,100 @@
|
|||
/***************************************************
|
||||
|
||||
A sprite built off this config:
|
||||
{
|
||||
image: image,
|
||||
grid:{ // in frames
|
||||
width: 2,
|
||||
height: 2
|
||||
},
|
||||
frame:{ // in pixels
|
||||
width: 100,
|
||||
height: 100
|
||||
},
|
||||
anchor:{ // in pixels. optional.
|
||||
x: 10,
|
||||
y: 30
|
||||
},
|
||||
frameNames:[ // optional
|
||||
"one",
|
||||
"two",
|
||||
"three"
|
||||
],
|
||||
x: 0, // optional
|
||||
y: 0, // optional
|
||||
rotation: 0, // optional
|
||||
scale: 1, // optinal
|
||||
squash: 1, // optional
|
||||
}
|
||||
|
||||
|
||||
***************************************************/
|
||||
|
||||
function Sprite(config){
|
||||
|
||||
var self = this;
|
||||
|
||||
// Sprite image & dimensions
|
||||
self.image = config.image;
|
||||
self.grid = config.grid;
|
||||
self.frame = config.frame;
|
||||
|
||||
// Sprite anchor
|
||||
self.anchor = {};
|
||||
self.anchor.x = config.anchor.x || 0;
|
||||
self.anchor.y = config.anchor.y || 0;
|
||||
|
||||
// Current frame
|
||||
self.currentFrame = 0;
|
||||
self.currentFrameName = "";
|
||||
self.frameNames = config.frameNames || [];
|
||||
self.gotoFrame = function(index){
|
||||
self.currentFrame = index;
|
||||
self.currentFrameName = self.frameNames[self.currentFrame] || "";
|
||||
};
|
||||
self.gotoFrameByName = function(name){
|
||||
var index = self.frameNames.indexOf(name);
|
||||
self.gotoFrame(index);
|
||||
};
|
||||
self.gotoFrame(0);
|
||||
|
||||
// Other transformations
|
||||
self.x = config.x || 0;
|
||||
self.y = config.y || 0;
|
||||
self.rotation = config.rotation || 0;
|
||||
self.scale = config.scale || 1;
|
||||
self.squash = config.squash || 1;
|
||||
|
||||
// Draw frame!
|
||||
self.draw = function(ctx){
|
||||
|
||||
ctx.save();
|
||||
|
||||
// Which part of image to draw?
|
||||
var sx = self.currentFrame % self.grid.width;
|
||||
var sy = Math.floor((self.currentFrame - sx)/self.grid.width);
|
||||
var fw = self.frame.width;
|
||||
var fh = self.frame.height;
|
||||
|
||||
// Translate...
|
||||
var dx = self.x;
|
||||
var dy = self.y;
|
||||
ctx.translate(dx, dy);
|
||||
|
||||
// Scale
|
||||
var scaleX = self.scale * self.squash;
|
||||
var scaleY = self.scale / self.squash;
|
||||
ctx.scale(scaleX, scaleY);
|
||||
|
||||
// Draw it!
|
||||
ctx.drawImage(
|
||||
self.image,
|
||||
sx*fw, sy*fh, fw, fh,
|
||||
-self.anchor.x, -self.anchor.y, fw/2, fh/2
|
||||
);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
(function(b){var a={},e=b.c_||{};a.publish=function(f,c){for(var a=e[f],d=a?a.length:0;d--;)a[d].apply(b,c||[])};a.subscribe=function(a,c){e[a]||(e[a]=[]);e[a].push(c);return[a,c]};a.unsubscribe=function(a,c){var b=e[c?a:a[0]];c=c||a[1];for(var d=b?b.length:0;d--;)b[d]===c&&b.splice(d,1)};"object"===typeof module&&module.exports?module.exports=exports=a:"function"===typeof define&&define.amd?define(function(){return a}):"object"===typeof b&&(b.publish=a.publish,b.subscribe=a.subscribe,b.unsubscribe=
|
||||
a.unsubscribe)})(this.window);
|
|
@ -0,0 +1,8 @@
|
|||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', 'scenes/demo.md?v='+Math.random());
|
||||
xhr.onload = function() {
|
||||
if(xhr.status===200){
|
||||
Game.onload(xhr.responseText);
|
||||
}
|
||||
};
|
||||
xhr.send();
|
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
|
@ -7,6 +7,13 @@ body{
|
|||
background: #ddd;
|
||||
}
|
||||
|
||||
.no_select{
|
||||
-webkit-user-select: none; /* Safari 3.1+ */
|
||||
-moz-user-select: none; /* Firefox 2+ */
|
||||
-ms-user-select: none; /* IE 10+ */
|
||||
user-select: none; /* Standard syntax */
|
||||
}
|
||||
|
||||
#game_container{
|
||||
|
||||
position: absolute;
|
||||
|
@ -107,38 +114,17 @@ body{
|
|||
/***********************************/
|
||||
/***********************************/
|
||||
|
||||
#game_hp{
|
||||
position: absolute;
|
||||
width: 360px;
|
||||
height: 80px;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
|
||||
background: rgb(204,204,204);
|
||||
background: linear-gradient(180deg, rgba(204,204,204,1) 80%, rgba(204,204,204,0) 100%);
|
||||
canvas{
|
||||
border: none;
|
||||
}
|
||||
#game_hp > div{
|
||||
position: absolute;
|
||||
top:25px;
|
||||
width: 150px;
|
||||
height: 20px;
|
||||
background: #ff4040;
|
||||
}
|
||||
#game_hp > #hp_human{
|
||||
left: 20px;
|
||||
transform: skew(15deg);
|
||||
}
|
||||
#game_hp > #hp_wolf{
|
||||
right: 20px;
|
||||
transform: skew(-15deg);
|
||||
}
|
||||
|
||||
/***********************************/
|
||||
/***********************************/
|
||||
/***********************************/
|
||||
|
||||
#game_canvas{
|
||||
position: absolute;
|
||||
top:0; left:0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#game_hp{
|
||||
position: absolute;
|
||||
width: 360px;
|
||||
height: 100px;
|
||||
top:0; left:0;
|
||||
}
|
Loading…
Reference in New Issue