clintbellanger / Karma-Slots

Simple HTML5/js/canvas slot machine game
http://clintbellanger.net/karma/
184 stars 86 forks source link

Canvas Slowing over time. #1

Closed Alliexx closed 11 years ago

Alliexx commented 11 years ago

First of all, my thanks to you for this awesome way of creating a slot like reel, this is a very interesting way of doing it. There is some issues with the speed and acceleration tweaking, but i seem to be able to find some working combination. Most annoying is though, when sizing this sample up in image pixel size and canvas size the speed is slowing after each run. I'm a real beginner here with this HTML/Java stuff, i can't figure out why this is happening.

Greetings, Alphons

clintbellanger commented 11 years ago

Do you have an example of this error happening that I can try?

For reference, I also have this version that I made to test larger images: http://clintbellanger.net/rage/ But I'm not getting any noticeable canvas slowing over time (using Chrome).

Alliexx commented 11 years ago

Hi there,

I never expected anybody home for this anymore, and so quick. Like i said, i'm a beginner and still learning what your code exactly does.

I have enlarged the reelstrip graphic and made it so it houses 35 symbols (last reel has all special symbols so i had to include the whole reel) Each reel has now 24 slots. I also had to made some case statement to check the last reel. I will just paste the whole "slot.js" source.

//Slot.js --------------------------------------------------------------------- //-----------------------------------------------------------------------------

/**

Copyright (c) 2012 Clint Bellanger

MIT License:

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Sounds by Brandon Morris (CC-BY 3.0) Art by Clint Bellanger (CC-BY 3.0)

*/

var FPS = 60; setInterval(function() { logic(); render(); }, 1000/FPS);

// html elements var can; // canvas var ctx; // context var log_p; // log paragraph var cred_p; // credits paragraph

var symbols_loaded = false; var reels_bg_loaded = false;

// art var symbols = new Image(); var reels_bg = new Image(); var snd_reel_stop = new Array(); var snd_win;

symbols.src = "images/BSReelsbig.png"; reels_bg.src = "images/reels_bg.png"; // this size is adjusted too....

snd_win = new Audio("sounds/win.wav"); snd_reel_stop[0] = new Audio("sounds/reel_stop.wav"); snd_reel_stop[1] = new Audio("sounds/reel_stop.wav"); snd_reel_stop[2] = new Audio("sounds/reel_stop.wav");

// enums var STATE_REST = 0; var STATE_SPINUP = 1; var STATE_SPINDOWN = 2; var STATE_REWARD = 3;

// config var reel_count = 3; var reel_positions = 24; var symbol_size = 76; var symbol_count = 35; var reel_pixel_length = reel_positions * symbol_size; var row_count = 3; var stopping_distance = 532; // not exactly know what this does..... var max_reel_speed = 32; var spinup_acceleration = 2; var spindown_acceleration = 1; var starting_credits = 100; var reward_delay = 3; // how many frames between each credit tick var reward_delay_grand = 1; // delay for grand-prize winning var reward_grand_threshhold = 25; // count faster if the reward is over this size

var match_payout = new Array(symbol_count); match_payout[0] = 250; // BAR match_payout[1] = 6; // GRAPE match_payout[2] = 8; // KERS match_payout[3] = 10; // ORANGE match_payout[4] = 15; // SEVEN match_payout[5] = 20; // LEMON match_payout[6] = 25; // APPLE match_payout[7] = 50; // STAR match_payout[8] = 75; // BELL match_payout[9] = 250; // MELON match_payout[10] = 100; // KERS/25 tempb = 2 match_payout[11] = 250; // Bar/1 temps = 0 match_payout[12] = 6; // Lemon/4 temps = 5 match_payout[13] = 8; // kers/7 temps = 2 match_payout[14] = 10; // ORANGE/10 temps = 3 match_payout[15] = 15; // lemon/18 temps = 5 match_payout[16] = 20; // bell/16 temps = 8 match_payout[17] = 25; // kers/19 temps = 2 match_payout[18] = 50; // grape/22 temps = 1 match_payout[19] = 75; // BELL/2 temps = 8 match_payout[20] = 250; // orange/5 temps = 3 match_payout[21] = 100; // lemon/8 temps = 5 match_payout[22] = 20; // bell/11 temps = 8 match_payout[23] = 25; // kers/14 temps = 2 match_payout[24] = 50; // star/17 temps = 7 match_payout[25] = 75; // melon/20 temps = 9 match_payout[26] = 250; // orange/23temps = 3 match_payout[27] = 100; // bell/3 temps = 8 match_payout[28] = 100; // kers/6 temps = 2 match_payout[29] = 20; // orange/9 temps = 3 match_payout[30] = 25; // apple/12 temps = 6 match_payout[31] = 50; // seven/15 temps = 4 match_payout[32] = 75; // lemon/18 temps = 5 match_payout[33] = 250; // bell/21 temps = 8 match_payout[34] = 100; // kers/24 temps = 2

var payout_ups = 6; // Any 3 Ups var payout_downs = 2; // Any 3 Downs

var reel_area_left = 76; var reel_area_top = 76; var reel_area_width = 228; var reel_area_height = 228;

// set up reels var reels = new Array(reel_count); reels[0] = new Array(0,1,2,3,4,5,6,3,5,4,1,6,1,7,6,8,3,1,6,9,5,1,3,6); reels[1] = new Array(0,6,9,1,6,9,10,5,2,6,9,2,3,7,4,1,6,9,2,5,1,6,9,8); reels[2] = new Array(11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34);

var reel_position = new Array(reel_count); for (var i=0; i<reel_count; i++) { reel_position[i] = Math.floor(Math.random() * reel_positions) * symbol_size; }

var stopping_position = new Array(reel_count); var start_slowing = new Array(reel_count);

// reel spin speed in pixels per frame var reel_speed = new Array(reel_count); for (var i=0; i<reel_count; i++) { reel_speed[i] = 0; }

var result = new Array(reel_count); for (var i=0; i<reel_count; i++) { result[i] = new Array(row_count); }

var game_state = STATE_REST; var credits = starting_credits; var payout = 0; var reward_delay_counter = 0; var playing_lines;

//---- Render Functions ---------------------------------------------

function draw_symbol(symbol_index, x, y) { var symbol_pixel = symbol_index * symbol_size; ctx.drawImage(symbols, 0,symbol_pixel,symbol_size,symbol_size, x+reel_area_left,y+reel_area_top,symbol_size,symbol_size); }

function render_reel() {

// clear reel //ctx.drawimage(); ctx.drawImage(reels_bg, reel_area_left, reel_area_top);

// set clipping area ctx.beginPath(); ctx.rect(reel_area_left, reel_area_top, reel_area_width, reel_area_height); ctx.clip();

var reel_index; var symbol_offset; var symbol_index; var x; var y;

for (var i=0; i<reel_count; i++) { for (var j=0; j<row_count +1; j++) {

  reel_index = Math.floor(reel_position[i] / symbol_size) + j;
  symbol_offset = reel_position[i] % symbol_size;

  // reel wrap
  if (reel_index >= reel_positions) reel_index -= reel_positions;

  // symbol lookup
  symbol_index = reels[i][reel_index];

  x = i * symbol_size;
  y = j * symbol_size - symbol_offset;

  draw_symbol(symbol_index, x, y);

}

} }

function highlight_line(line_num) {

ctx.strokeStyle = "orange"; var ss = symbol_size;

// top row if (line_num == 2 || line_num == 4) { ctx.strokeRect(reel_area_left, reel_area_top, symbol_size-1, symbol_size-1); // top left } if (line_num == 2) { ctx.strokeRect(reel_area_left + ss, reel_area_top, ss-1, ss-1); // top middle } if (line_num == 2 || line_num == 5) { ctx.strokeRect(reel_area_left + ss + ss, reel_area_top, ss-1, ss-1); // top right }

// middle row if (line_num == 1) { ctx.strokeRect(reel_area_left, reel_area_top + ss, ss-1, ss-1); // top left } if (line_num == 1 || line_num == 4 || line_num == 5) { ctx.strokeRect(reel_area_left + ss, reel_area_top + ss, ss-1, ss-1); // top middle } if (line_num == 1) { ctx.strokeRect(reel_area_left + ss + ss, reel_area_top + ss, ss-1, ss-1); // top right }

// bottom row if (line_num == 3 || line_num == 5) { ctx.strokeRect(reel_area_left, reel_area_top + ss + ss, ss-1, ss-1); // top left } if (line_num == 3) { ctx.strokeRect(reel_area_left + ss, reel_area_top + ss + ss, ss-1, ss-1); // top middle } if (line_num == 3 || line_num == 4) { ctx.strokeRect(reel_area_left + ss + ss, reel_area_top + ss + ss, ss-1, ss-1); // top right }

}

// render all art needed in the current frame function render() {

if (game_state == STATE_SPINUP || game_state == STATE_SPINDOWN) { render_reel(); }

}

//---- Logic Functions ---------------------------------------------

function set_stops() { for (var i=0; i<reel_count; i++) {

start_slowing[i] = false;

stop_index = Math.floor(Math.random() * reel_positions);
stopping_position[i] = stop_index * symbol_size;

stopping_position[i] += stopping_distance;
if (stopping_position[i] >= reel_pixel_length) stopping_position[i] -= reel_pixel_length;

// convenient here to remember the winning positions
for (var j=0; j<row_count; j++) {
  result[i][j] = stop_index + j;
  if (result[i][j] >= reel_positions) result[i][j] -= reel_positions;

  // translate reel positions into symbol
  result[i][j] = reels[i][result[i][j]];
}

} }

function move_reel(i) { reel_position[i] -= reel_speed[i];

// wrap if (reel_position[i] < 0) { reel_position[i] += reel_pixel_length; } }

// handle reels accelerating to full speed function logic_spinup() {

for (var i=0; i<reel_count; i++) {

// move reel at current speed
move_reel(i);
// accelerate speed
reel_speed[i] += spinup_acceleration;

}

// if reels at max speed, begin spindown // crappy way, becaUSE with wrong speed and acceleration sometimes speed is never met value if (reel_speed[0] == max_reel_speed) {

// calculate the final results now, so that spindown is ready
set_stops();
game_state = STATE_SPINDOWN;

} }

// handle reel movement as the reels are coming to rest function logic_spindown() {

// if reels finished moving, begin rewards if (reel_speed[reel_count-1] == 0) {

calc_reward();
game_state = STATE_REWARD;

}

for (var i=0; i<reel_count; i++) {

// move reel at current speed
move_reel(i);    
// start slowing this reel?
if (start_slowing[i] == false) {

  // if the first reel, or the previous reel is already slowing
  var check_position = false;
  if (i == 0) check_position = true;
  else if (start_slowing[i-1]) check_position = true;

  if (check_position) {
      //log_p.innerHTML = reel_position[i] +" "+ stopping_position[i] +" "+ reel_speed[i];
    //log_p.innerHTML = "we " + reel_speed[i];
    //log_p.innerHTML = "we are here now ??";
    if ((reel_position[i] >= stopping_position[i]) && (reel_position[i] <= stopping_position[i]+76)) {  // another change so we actually are able to line up reel pos with stop poss...
        reel_position[i] = stopping_position[i];
          start_slowing[i] = true;

    }
  }
}
else {
  if (reel_speed[i] > 0) {
    reel_speed[i] -= spindown_acceleration;

    if (reel_speed[i] == 0) {
      try {
        snd_reel_stop[i].currentTime = 0;
        snd_reel_stop[i].play();
      } catch(err) {};
    }

  }
}

}

}

// count up the reward credits, play sound effects, etc. function logic_reward() {

if (payout == 0) { game_state = STATE_REST; return; }

// don't tick up rewards each frame, too fast if (reward_delay_counter > 0) { reward_delay_counter--; return; }

payout--; credits++; cred_p.innerHTML = "Karma (" + credits + ")";

if (payout < reward_grand_threshhold) { reward_delay_counter = reward_delay; } else { // speed up big rewards reward_delay_counter += reward_delay_grand; }

}

// update all logic in the current frame function logic() {

// REST to SPINUP happens on an input event

if (game_state == STATE_SPINUP) { logic_spinup(); } else if (game_state == STATE_SPINDOWN) { logic_spindown(); } else if (game_state == STATE_REWARD) { logic_reward(); }

}

// given an input line of symbols, determine the payout function calc_line(s1, s2, s3) {

// perfect match for base symbols !!! // How to change last reel to symbols as reel 1 and 2 // Case statement ?? var temps,tempb;

if (s2 == 10){ tempb = 2; }else{ tempb = s2; }

switch (s3) { case 11: temps = 0; //bar break; case 12: case 15: case 21: case 32: temps = 5; //lemon break; case 13: case 17: case 23: case 28: case 34: temps = 2; //kers break; case 14: case 20: case 26: case 29: temps = 3; //orange break; case 16: case 19: case 22: case 27: case 33: temps = 8; //bell break; case 18: temps = 1; //grape break; case 24: temps = 7; //star break; case 25: temps = 9; //melon break; case 30: temps = 6; //apple break; case 31: temps = 4; //seven break;

    }

if (s1 == tempb && tempb == temps) { //removed and replaced (s2, s3 ) return match_payout[s1]; } log_p.innerHTML = s1+" "+tempb+" "+temps; //+ "
\n"

}

// calculate the reward function calc_reward() { payout = 0;

var partial_payout;

// Line 1 partial_payout = calc_line(result[0][1], result[1][1], result[2][1]); if (partial_payout > 0) { log_p.innerHTML += "Line 1 pays " + partial_payout + "
\n"; payout += partial_payout; highlight_line(1); }

if (playing_lines > 1) {

// Line 2
partial_payout = calc_line(result[0][0], result[1][0], result[2][0]);
if (partial_payout > 0) {
  log_p.innerHTML += "Line 2 pays " + partial_payout + "<br />\n";
  payout += partial_payout;
  highlight_line(2);
}

// Line 3
partial_payout = calc_line(result[0][2], result[1][2], result[2][2]);
if (partial_payout > 0) {
  log_p.innerHTML += "Line 3 pays " + partial_payout + "<br />\n";
  payout += partial_payout;
  highlight_line(3);
}

}

if (playing_lines > 3) {

// Line 4
partial_payout = calc_line(result[0][0], result[1][1], result[2][2]);
if (partial_payout > 0) {
  log_p.innerHTML += "Line 4 pays " + partial_payout + "<br />\n";
  payout += partial_payout;
  highlight_line(4);
}

// Line 5
partial_payout = calc_line(result[0][2], result[1][1], result[2][0]);
if (partial_payout > 0) {
  log_p.innerHTML += "Line 5 pays " + partial_payout + "<br />\n";
  payout += partial_payout;
  highlight_line(5);
}

}

if (payout > 0) { try { snd_win.currentTime = 0; snd_win.play(); } catch(err) {}; }

}

//---- Input Functions ---------------------------------------------

function handleKey(evt) { if (evt.keyCode == 32) { // spacebar if (game_state != STATE_REST) return;

if (credits >= 5) spin(5);
else if (credits >= 3) spin(3);
else if (credits >= 1) spin(1);

} }

function spin(line_choice) {

if (game_state != STATE_REST) return; if (credits < line_choice) return;

credits -= line_choice; playing_lines = line_choice;

cred_p.innerHTML = "Sparma (" + credits + ")"; log_p.innerHTML = "";

game_state = STATE_SPINUP;

}

//---- Init Functions -----------------------------------------------

function init() { can = document.getElementById("slots"); ctx = can.getContext("2d"); log_p = document.getElementById("log"); cred_p = document.getElementById("credits");

cred_p.innerHTML = "Sparma (" + credits + ")"

window.addEventListener('keydown', handleKey, true);

symbols.onload = function() { symbols_loaded = true; if (symbols_loaded && reels_bg_loaded) render_reel(); };

reels_bg.onload = function() { reels_bg_loaded = true; if (symbols_loaded && reels_bg_loaded) render_reel(); };

}

// end slot.js ----------------------------------------------------------------- //------------------------------------------------------------------------------

I'm now fooling around with it on a different computer and now it seems ok, but i'm not sure about it. I will stay on this and make sure it is working flawless.

It is a bit strange, now i'm fooling around with it on a different PC, this one runs WINXP(32) and Firefox browser, all seems fine here ???? At home i'm running WIN7(64) and firefox and after running for a couple of spins the drawings get slower each run, here at work it seems all fine.

Afterall it seems it has to do with the PC i'm trying it on, maybe there is NO problem with your code, if so, i'm sorry i brought it up.

Thank you very much again for the nice sample code.

Date: Tue, 19 Feb 2013 12:12:04 -0800 From: notifications@github.com To: Karma-Slots@noreply.github.com CC: alliexx098@hotmail.com Subject: Re: [Karma-Slots] Canvas Slowing over time. (#1)

Do you have an example of this error happening that I can try?

For reference, I also have this version that I made to test larger images: http://clintbellanger.net/rage/

But I'm not getting any noticeable canvas slowing over time (using Chrome).

          —

          Reply to this email directly or view it on GitHub.
Alliexx commented 11 years ago

Hi again,

I have been testing as crazy and it seems that firefox running under windows7 64bit is the problem. IE is ok on win7. On Windows XP all browsers work fine with it.

So your code seems sound :) It is just that i like the simplicity of it, it doesn.'t use any other scripts, i love it and i will use it for my slot machine project .

Thank so much for this awesome example.

Greetings, Alphons de Wild

Date: Tue, 19 Feb 2013 12:12:04 -0800 From: notifications@github.com To: Karma-Slots@noreply.github.com CC: alliexx098@hotmail.com Subject: Re: [Karma-Slots] Canvas Slowing over time. (#1)

Do you have an example of this error happening that I can try?

For reference, I also have this version that I made to test larger images: http://clintbellanger.net/rage/

But I'm not getting any noticeable canvas slowing over time (using Chrome).

          —

          Reply to this email directly or view it on GitHub.
clintbellanger commented 11 years ago

No problem. Glad you're enjoying the code! This was the first thing I ever wrote using HTML5/Canvas/JS and was still learning a lot.