@tech4teachers/

Platform game with 2 players and proto-coins

HTML, CSS, JS

No description

fork
loading
Files
  • index.html
  • script.js
  • style.css
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
<!-- This is a game prototype based on Loktar's work on somethinghitme.com and his jsfiddle.net channel -->
<!-- All CSS, HTML5, and Javascript are contained within this one file...normally we should make them separate files -->
<html><link type="text/css" id="dark-mode" rel="stylesheet" href=""><style type="text/css" id="dark-mode-custom-style"></style><head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>Platform tutorial By Mr Boyd and Loktar</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="robots" content="noindex, nofollow">
  <meta name="googlebot" content="noindex, nofollow">
  <meta name="viewport" content="width=device-width, initial-scale=1">


  <script type="text/javascript" src="/js/lib/dummy.js"></script>

    <link rel="stylesheet" type="text/css" href="/css/result-light.css">

  <!-- This is the CSS code that would/could go in its own separate .css file ....later -->
  <style id="compiled-css" type="text/css">
      canvas {
    border:1px solid #000;
}
  </style>



</head>


<body>
    <canvas id="canvas" width="1200" height="600"></canvas>

  <!-- TODO: Missing CoffeeScript 2  which might refactor or simplfy better????? -->
    <!-- This is the Javascript which could also have been put in its own separate .js file...later we can do that if we call the separate file in the header -->

  <script type="text/javascript">



(function () {
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    window.requestAnimationFrame = requestAnimationFrame;
})();

// you can create multiple variables all at once instead of saying var... var...var... over and over

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d"),
    width = 1200,
    height = 600,
    player = {
        x: width / 2, 
        //places the player at half way or the middle ( width divided by 2 is halfway)
        y: height - 15, // starts the player 15 pixels above the bottom of the canvas or screen
        width: 10,
        height: 10,
        speed: 3,
        velX: 0, // experiment with these 
        velY: 0,
        jumping: false, // this just sets whether you are CURRENTLY jumping
        grounded: false
    },


    player2 = {
        x: width / 4, //places the player at half way or the middle ( width divided by 2 is halfway)
        y: height - 15, // starts the player 15 pixels above the bottom of the canvas or screen
        width: 20,
        height: 20,
        speed: 3,
        velX: 0, // experiment with these but I think friction and gravity are related to these use later you will see player.velX *= friction; which currently results in zero times 0.8...which is still zero
        velY: 0,
        jumping: false, // this just sets whether you are CURRENTLY jumping
        grounded: false
    },
    keys = [],
    friction = 0.8,  // try changing this later ...see my comments above about friction and velX being interrelated
    gravity = 0.1;

var boxes = []; // here is where we design the level obstacles and platforms [] is an "array" or a group of things that have more than one attribute each...or a group of grouped ideas

// dimensions of each of the platform boxes and where they are created ( top left corner)
boxes.push({
    x: 0,
    y: 0,
    width: 10,
    height: height
});
boxes.push({
    x: 0,
    y: height - 2,
    width: width,
    height: 50
});
boxes.push({
    x: width - 10,
    y: 0,
    width: 50,
    height: height
});

boxes.push({
    x: 120,
    y: 210,
    width: 80,
    height: 20
});
boxes.push({
    x: 270,
    y: 550,
    width: 280,
    height: 10
});
boxes.push({
    x: 820,
    y: 300,
    width: 80,
    height: 10
    //ctx.fillStyle = '#FD0';
    //ctx.fillRect(x, y, width, height);
});

boxes.push({  //try changing the locations and sizes of the obstacles/platforms you can always add more or delete a few
    x: 470,
    y: 450,
    width: 140,
    height: 40
});
boxes.push({  //try changing the locations and sizes of the obstacles/platforms you can always add more or delete a few
    x: 300,
    y: 300,
    width: 20,
    height: 10
});

var coins = []; // here is where we design the level obstacles and platforms [] is an "array" or a group of things that have more than one attribute each...or a group of grouped ideas
// dimensions of each of the platform boxes and where they are created ( top left corner)
coins.push({
    x: 60,
    y: 60,
    width: 15,
    height: 15,
});
coins.push({
    x: 160,
    y: 175,
    width: 25,
    height: 25,
});

canvas.width = width;
canvas.height = height;

// this UPDATE function is also what we could call the "game loop"
function update() {
    // check control keys pressed by the player...could you add a second player and second set of keys
    if (keys[38] ) { // removed the spacebar OR option || keys[32]
        // up arrow or _______ go look up the ascii key assignment address of 32...whcih key is 32????  BTW the || means "or"
        if (!player.jumping && player.grounded) {
            // the ! before player above means "NOT"...so we are checking if the player is not jumping  && means AND, so both conditions need to be met for this code to be acted upon in the computer
            player.jumping = true;
            player.grounded = false;
            player.velY = -player.speed * 2;
        }
    }
    
    if (keys[87] ) { //it could be a cool quirk of the game if both characters were forced to jump at the same time and both by making it or w or up button
        // up arrow or _______ go look up the ascii key assignment address of 32...whcih key is 32????  BTW the || means "or"
        if (!player2.jumping && player2.grounded) {
            // the ! before player above means "NOT"...so we are checking if the player is not jumping  && means AND, so both conditions need to be met for this code to be acted upon in the computer
            player2.jumping = true;
            player2.grounded = false;
            player2.velY = -player2.speed * 2;
        }
    }

    if (keys[39]) {
        // right arrow
        if (player.velX < player.speed) {
            player.velX++;
        }
    }
    if (keys[37]) {
        // left arrow
        if (player.velX > -player.speed) {
            player.velX--;
        }
    }

    if (keys[68]) {
        // right arrow
        if (player2.velX < player2.speed) {
            player2.velX++;
        }
    }
    if (keys[65]) {
        // left arrow
        if (player2.velX > -player2.speed) {
            player2.velX--;
        }
    }

    player.velX *= friction;
    player.velY += gravity;

    player2.velX *= friction;
    player2.velY += gravity;




    ctx.clearRect(0, 0, width, height);
        for (var i = 0; i < coins.length; i++) {
        ctx.fillStyle = "gold";
        ctx.rect(coins[i].x, coins[i].y, coins[i].width, coins[i].height);
        ctx.fillRect(coins[i].x, coins[i].y, coins[i].width, coins[i].height);}

    ctx.fillStyle = "black"; // must be here and NOT INSIDE the for loop so that player controls work...weird
    ctx.beginPath();

    player.grounded = false;
    for (var i = 0; i < boxes.length; i++) {
        ctx.rect(boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);

        var dir = colCheck(player, boxes[i]);  // we "call" the collision detection function colCheck that we will write NEXT and send it which things we want it to check are colliding ( or not colliding), these two PARAMETERS are player and ALL the boxes, imagine if also checked coins and enemies

        if (dir === "l" || dir === "r") {
            player.velX = 0;
            player.jumping = false;
        } else if (dir === "b") {
            player.grounded = true;
            player.jumping = false;
        } else if (dir === "t") {
            player.velY *= -1;
        }

    }

    if(player.grounded){
         player.velY = 0;
    }

    player.x += player.velX;
    player.y += player.velY;

    ctx.fill();
    ctx.fillStyle = "red"; //try changing this
    ctx.fillRect(player.x, player.y, player.width, player.height);


    player2.grounded = false; //must use player2 and create a new variable dir2 otherwise player 2 gets player one's collision detection values and they conflict
    for (var i = 0; i < boxes.length; i++) {
        //ctx.fillStyle = "black";  // not needed twice....this drawing of the boxes is already in player
        //ctx.rect(boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height); // not needed twice....this drawing of the boxes is already in player

//just check if player2 collides withthe boxes drawn above
        var dir2 = colCheck(player2, boxes[i]);  // we "call" the collision detection function colCheck that we will write NEXT and send it which things we want it to check are colliding ( or not colliding), these two PARAMETERS are player and ALL the boxes, imagine if also checked coins and enemies

        if (dir2 === "l" || dir2 === "r") {
            player2.velX = 0;
            player2.jumping = false;
        } else if (dir2 === "b") {
            player2.grounded = true;
            player2.jumping = false;
        } else if (dir2 === "t") {
            player2.velY *= -1;
        }

    }

    if(player2.grounded){
         player2.velY = 0;
    }

    player2.x += player2.velX;
    player2.y += player2.velY;

    //ctx.fill(); // two of these breaks the code and make all boxes red also overriding the black fill
    ctx.fillStyle = "green"; //try changing this
    ctx.fillRect(player2.x, player2.y, player2.width, player2.height);



    requestAnimationFrame(update); // only one of these is needed per the whole  function ....NOT one per player
}


function colCheck(shapeA, shapeB) {    //shapeA gets the player info and shapeB gets the box info from the var dir request around line 149
    // get the vectors to check against
    var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
        vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
        // add the half widths and half heights of the objects
        hWidths = (shapeA.width / 2) + (shapeB.width / 2),
        hHeights = (shapeA.height / 2) + (shapeB.height / 2),
        colDir = null;

    // if the x and y vector are less than the half width or half height, they  must be inside the object, causing a collision!!!!!!!!!
    if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
        // figures out on which side we are colliding (top, bottom, left, or right)
        var oX = hWidths - Math.abs(vX),
            oY = hHeights - Math.abs(vY);
        if (oX >= oY) {
            if (vY > 0) {
                colDir = "t"; //t for top
                shapeA.y += oY;
            } else {
                colDir = "b"; // b for bottom
                shapeA.y -= oY;
            }
            
        } else {
            if (vX > 0) {
                colDir = "l";   //sets the collision to say "I hit something on the LEFT" side
                shapeA.x += oX;
            } else {
                colDir = "r";  // if you didn't hit something on the left side ....maybe you hit something on the RIGHT side
                shapeA.x -= oX;
            }
        }
    }
    return colDir;  // if none of the sides collided, colrDir stays "null" which is what we set it to at the start of this function
}

// as long as the eyboard key is pressed ...keep doing stuff
document.body.addEventListener("keydown", function (e) {
    keys[e.keyCode] = true;
});

//this next code stops the player action from continuing if we let up on the keyboard key
document.body.addEventListener("keyup", function (e) {
    keys[e.keyCode] = false;
});


window.addEventListener("load", function () {
    update();
});


</script>

<script>
    // tell the embed parent frame the height of the content
    if (window.parent && window.parent.parent){
      window.parent.parent.postMessage(["resultsFrame", {
        height: document.body.getBoundingClientRect().height,
        slug: ""
      }], "*")
    }

    // always overwrite window.name, in case users try to set it manually
    window.name = "result"
  </script>


</body>
Mario and Luigi meet The smirking Polar Bear</html>
result
console