How to initialize C Union structure members (using C89 Standard XC32 compiler2.5)? - structure

I have this union / structure
#define HOT_INI_DATA_SIZE 14
typedef union
{
struct
{
uint8_t OVER_LOAD_TEMP_BYTE_LOW;
uint8_t OVER_LOAD_TEMP_BYTE_HI;
uint8_t TEMP_CORRECTION_BYTE_LOW;
uint8_t TEMP_CORRECTION_BYTE_HI;
uint8_t STEAM_CORRECTION_BYTE;
uint8_t LEVEL_SENSOR_CALIBR_DATA[HOT_INI_DATA_SIZE - 5];
} fields;
uint8_t bytes[HOT_INI_DATA_SIZE];
} hot_cal_data_t;
I am trying to initalise it with carious methods but have no luck:
const hot_cal_data_t initialisationHotData =
{
{0xD4},
{3},
{0},
{0},
{0},
{16, 16, 16, 16, 16, 16, 16, 16, 16 }
};
It is complaining about extra braces around initializer but when I remove it the error changes.
When I try the newer C99 method:
{
{.fields.OVER_LOAD_TEMP_BYTE_LOW = 0xD4},
{.fields.OVER_LOAD_TEMP_BYTE_HI = 0x00},
...
};
it tells me the .fields is not recognized. so I have to assume that it uses the C98 method of only initializing the first union element.
Can anyone please tell me the correct syntax to get this initialized.

I have since figured it out.
It is using C89 standard and requires this syntax to initialize:
const hot_cal_data_t initialisationHotData =
{
{
0xD4,
0x03,
0,
0,
0,
{
16, //.LEVEL_SENSOR_CALIBR_DATA[0]
16, //.LEVEL_SENSOR_CALIBR_DATA[1]
16, //.LEVEL_SENSOR_CALIBR_DATA[2]
16, //.LEVEL_SENSOR_CALIBR_DATA[3]
16, //.LEVEL_SENSOR_CALIBR_DATA[4]
16, //.LEVEL_SENSOR_CALIBR_DATA[5]
16, //.LEVEL_SENSOR_CALIBR_DATA[6]
16, //.LEVEL_SENSOR_CALIBR_DATA[7]
16 //[8]
}
}
};

Related

Time promise requests to an API using setInterval or setTimeout

I have this issue - I'm trying to fetch a data from a constant url that accepts an integer ID.
I have these integers stacked in array.
I do not want to flood the server with requests so I tried using setInterval and setTimeout to time the requests.
I did take in consideration that a promise might take some time to complete but couldn't figure out how to explicitly apply that.
The results of this code are just:
"[] 1"
const axios = require('axios')
const dataFile = require('../data/car_data')
const modelNameUrl = 'https://www.gov.il/api/mot/carlistprice/api/modelName?yazran_id='
const carId = dataFile.map(data => data.manufacturer_id)
const fetch = async (id) => {
const dataFetched = await axios.get(`${modelNameUrl}${id}`).then()
return dataFetched.data.dgamim_yazran
}
let index = 0
setInterval(async () => {
const data = await fetch(index)
index++
console.log(data, index)
}, 10000)
Additional code for further debugging:
const axios = require('axios')
// const dataFile = require('../data/car_data')
// dataFile.map(data => data.manufacturer_id)
const modelNameUrl = 'https://www.gov.il/api/mot/carlistprice/api/modelName?yazran_id='
let dataArray = []
const fetch = async (id) => {
const dataFetched = await axios.get(`${modelNameUrl}${id}`)
return dataFetched.data.dgamim_yazran
}
function delay(t) {
return new Promise(resolve => setTimeout(resolve, t));
}
let integerSource = [
6, 67, 4, 5, 9, 60, 7, 30, 107, 113, 19,
120, 15, 17, 12, 59, 3, 129, 56, 1, 124, 29,
26, 64, 33, 63, 131, 112, 2, 39, 133, 38, 40,
48, 52, 53, 54, 50, 13, 110, 51, 57, 68, 23,
44, 22, 41, 21, 10, 32, 47, 45, 11
]
async function runLoop() {
for (let index of integerSource) {
try {
const data = await fetch(index);
console.log(data, index);
await delay(5000);
} catch (e) {
console.log(`Error on index ${index}`, e);
throw new Error
}
}
}
runLoop().then(() => {
console.log("all done");
}).catch(err => {
console.log("ended with error\n", err);
});
I'd suggest just using a for loop with await and then a promise-returning delay. This will space out your API calls from when they finish, not from when they started. Your existing scheme does not increment the index right away so it could even make duplicate calls to fetch().
You say you have the desired integers stack in an array, but don't show that in your code. You can either use a for loop that just increments an index or you can use the for loop to pull integers from your array.
function delay(t) {
return new Promise(resolve => setTimeout(resolve, t));
}
let integerSource = [...]; // your array of integer values
async function runLoop() {
for (let index of integerSource) {
try {
const data = await fetch(index);
conole.log(data, index);
await delay(10000);
} catch(e) {
conole.log(`Error on index ${index}`, e);
// decide here whether you continue with further requests
// or throw e to stop further processing
}
}
}
// run the loop here
runLoop().then(() => {
console.log("all done");
}).catch(err => {
console.log("ended with error");
});

CasperJS File Download Times Out After 30 Seconds

I'm using CasperJS to download a 15 MB file. In the browser, the download takes about 3 minutes to complete. With Casper, the .download function for the same url returns after exactly 30 seconds, and the file written to disk is 0 bytes. I've tried setting longer timeouts like this:
var casper = require("casper").create({
pageSettings: {
webSecurityEnabled: false
},
waitTimeout: 500000,
stepTimeout: 500000
});
But they have no effect. Here's my download function:
casper.on('resource.received', function (resource) {
var url, file;
if ((resource.url.indexOf("myDownloadUniqueString=") !== -1) ) {
this.echo(resource.url); // the echo'ed url can be downloaded in a web browser
url = resource.url;
file = "downloaded_file.wav"; // this will be 0 bytes
try {
var fs = require("fs"); // phantom js file system (not node)
casper.download(resource.url, file);
} catch (e) {
this.echo(e); // no error is thrown
}
}
});
Any ideas? Perhaps an issue with the PhantomJS fs methods, but that documentation is incomplete...
I solved this problem (for an Excel .xls binary download taking >30s, 6Mb approx) by running an async XMLHTTPrequest (xhr) manually within an evaluate function, then writing the result to a global (window) variable, and waiting for this global to be set.
On the xhr object, you can set a custom timeout, 15 * 60 * 1000 = 15 mins in the example below.
Care needs to be taken with encoding binary downloads as ascii / base64, and then decoding them to write a binary file. This could be adapted / simplified for text downloads.
var fs = require('fs');
var casper = require('casper').create({
//options here
});
var xhr = this.evaluate(function(url){
var xhr = new XMLHttpRequest();
xhr.timeout = 15 * 60 * 1000;
xhr.overrideMimeType("text/plain; charset=x-user-defined");
xhr.open("GET", url); // synchronous request banned, so use waitfor to wait on a global variable
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
//if (xhr.status == 200) {
window.xhrstatus = xhr.status; //write to a global (window) variable
window.xhrResponseText = __utils__.encode(xhr.responseText); //base64 encode using casper functions (btoa fails)
//}
}
};
xhr.send(null);
return true;
},'http://example.com/download.xls');
casper.waitFor(function() {
return this.getGlobal('xhrstatus') != undefined;
}, function() {
this.echo('XHR status: ' + this.getGlobal('xhrstatus'));
this.echo('Saving report...');
//http://phantomjs.org/api/fs/method/is-writable.html to check if file writable first
//decode using casper clientutil function and then write binary file
fs.write('saveFileName.xls', decode(this.getGlobal('xhrResponseText')), 'wb');
},null,15*60*1000);
The encode / decode functions from casper.js clientutils library look like this. These seem to work where Javascript's atob() and btoa() don't.
/*
* encode / decode function from casper.js clientutils
* https://github.com/casperjs/casperjs/blob/master/modules/clientutils.js
* Included here for reference - you could just reference the file in your code
*/
var BASE64_ENCODE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var BASE64_DECODE_CHARS = [
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
-1, 0, 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, -1, -1, -1, -1, -1,
-1, 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, -1, -1, -1, -1, -1
];
/**
* Decodes a base64 encoded string. Succeeds where window.atob() fails.
*
* #param String str The base64 encoded contents
* #return string
*/
var decode = function decode(str) {
/*eslint max-statements:0, complexity:0 */
var c1, c2, c3, c4, i = 0, len = str.length, out = "";
while (i < len) {
do {
c1 = BASE64_DECODE_CHARS[str.charCodeAt(i++) & 0xff];
} while (i < len && c1 === -1);
if (c1 === -1) {
break;
}
do {
c2 = BASE64_DECODE_CHARS[str.charCodeAt(i++) & 0xff];
} while (i < len && c2 === -1);
if (c2 === -1) {
break;
}
out += String.fromCharCode(c1 << 2 | (c2 & 0x30) >> 4);
do {
c3 = str.charCodeAt(i++) & 0xff;
if (c3 === 61) {
return out;
}
c3 = BASE64_DECODE_CHARS[c3];
} while (i < len && c3 === -1);
if (c3 === -1) {
break;
}
out += String.fromCharCode((c2 & 0XF) << 4 | (c3 & 0x3C) >> 2);
do {
c4 = str.charCodeAt(i++) & 0xff;
if (c4 === 61) {
return out;
}
c4 = BASE64_DECODE_CHARS[c4];
} while (i < len && c4 === -1);
if (c4 === -1) {
break;
}
out += String.fromCharCode((c3 & 0x03) << 6 | c4);
}
return out;
};
/**
* Base64 encodes a string, even binary ones. Succeeds where
* window.btoa() fails.
*
* #param String str The string content to encode
* #return string
*/
var encode = function encode(str) {
/*eslint max-statements:0 */
var out = "", i = 0, len = str.length, c1, c2, c3;
while (i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if (i === len) {
out += BASE64_ENCODE_CHARS.charAt(c1 >> 2);
out += BASE64_ENCODE_CHARS.charAt((c1 & 0x3) << 4);
out += "==";
break;
}
c2 = str.charCodeAt(i++);
if (i === len) {
out += BASE64_ENCODE_CHARS.charAt(c1 >> 2);
out += BASE64_ENCODE_CHARS.charAt((c1 & 0x3) << 4 | (c2 & 0xF0) >> 4);
out += BASE64_ENCODE_CHARS.charAt((c2 & 0xF) << 2);
out += "=";
break;
}
c3 = str.charCodeAt(i++);
out += BASE64_ENCODE_CHARS.charAt(c1 >> 2);
out += BASE64_ENCODE_CHARS.charAt((c1 & 0x3) << 4 | (c2 & 0xF0) >> 4);
out += BASE64_ENCODE_CHARS.charAt((c2 & 0xF) << 2 | (c3 & 0xC0) >> 6);
out += BASE64_ENCODE_CHARS.charAt(c3 & 0x3F);
}
return out;
};
How about adding resourceTimeout:
pageSettings: {
webSecurityEnabled: false,
resourceTimeout: 240000 //240s
},
This answer says it was added in PhantomJS 1.9, but is not documented yet.
To fix this you can casperjs-better-download
casper.on('resource.received', function (resource) {
var url, file;
if ((resource.url.indexOf("myDownloadUniqueString=") !== -1) ) {
this.echo(resource.url); // the echo'ed url can be downloaded in a web browser
url = resource.url;
file = "downloaded_file.wav"; // this will be 0 bytes
try {
var fs = require("fs"); // phantom js file system (not node)
//casper.download(resource.url, file);
var fiveMins = 60000 * 5;
betterDownload({
casper: casper,
url: final_url,
targetFilepath: '/usr/share/nginx/downloaded_file.wav',
waitTimeout: fiveMins
});
} catch (e) {
this.echo(e); // no error is thrown
}
}
});

Sorting an nsmutable array --> order is not being saved?

kind of a noob question maybe: I'm trying to sort an nsmutablearray, but somehow the order is not being stored.
typedef struct {
float distance;
int index;
} DistanceAndIndex;
i = 0;
NSMutableArray *orderedDistances = [NSMutableArray arrayWithCapacity:(self.wayPoints.count)];
CLLocation* rwp2 = [[CLLocation alloc] initWithLatitude:52.080752 longitude:4.7527251];
latLonToEcef(rwp2.coordinate.latitude, rwp2.coordinate.longitude, 0.0, &myX, &myY, &myZ);
for (routeWayPoint *rwp in [[self wayPoints] objectEnumerator]) {
double poiX, poiY, poiZ, e, n, u;
latLonToEcef(rwp.location.coordinate.latitude, rwp.location.coordinate.longitude, 0.0, &poiX, &poiY, &poiZ);
ecefToEnu(rwp2.coordinate.latitude, rwp2.coordinate.longitude, myX, myY, myZ, poiX, poiY, poiZ, &e, &n, &u);
DistanceAndIndex distanceAndIndex;
distanceAndIndex.distance = sqrtf(n*n + e*e);
distanceAndIndex.index = i;
NSLog(#"Index = %i, %f", i, distanceAndIndex.distance);
[orderedDistances insertObject:[NSData dataWithBytes:&distanceAndIndex length:sizeof(distanceAndIndex)] atIndex:i++];
}
i=0;
[orderedDistances sortUsingComparator:(NSComparator)^(NSData *a, NSData *b) {
const DistanceAndIndex *aData = (const DistanceAndIndex *)a.bytes;
const DistanceAndIndex *bData = (const DistanceAndIndex *)b.bytes;
if (aData->distance < bData->distance) {
return NSOrderedAscending;
} else if (aData->distance > bData->distance) {
return NSOrderedAscending;
} else {
return NSOrderedSame;
}
}];
for (NSData *d in [orderedDistances reverseObjectEnumerator]) {
const DistanceAndIndex *distanceAndIndex = (const DistanceAndIndex *)d.bytes;
NSLog(#"item: %i, %f", distanceAndIndex->index, distanceAndIndex->distance);
}
The output is the following:
[2021:907] Waypoints: 8
[2021:907] Index = 0, 230.078827
[2021:907] Index = 1, 171.626389
[2021:907] Index = 2, 36.015743
[2021:907] Index = 3, 103.174805
[2021:907] Index = 4, 238.837616
[2021:907] Index = 5, 278.074371
[2021:907] Index = 6, 288.319763
[2021:907] Index = 7, 321.953156
[2021:907] item: 7, 321.953156
[2021:907] item: 6, 288.319763
[2021:907] item: 5, 278.074371
[2021:907] item: 4, 238.837616
[2021:907] item: 3, 103.174805
[2021:907] item: 2, 36.015743
[2021:907] item: 1, 171.626389
[2021:907] item: 0, 230.078827
The array simply hasn't been reordered (for instance when looking at items 1,2 and 3). I feel like I'm overlooking something really basic. Any ideas?
Thanks!
You appear to be overlooking this typo:
if (aData->distance < bData->distance) {
return NSOrderedAscending;
} else if (aData->distance > bData->distance) {
return NSOrderedAscending;
} else {
return NSOrderedSame;
}
The second one should be NSOrderedDescending, I think.
You seem to have two if statements that both return NSOrderedAscending

What's the best way to perform the equivalent of DENSE_RANK on MongoDB?

SQL Server and Oracle both have DENSE_RANK functions. This allows you to, among other things, get the global ranking for a record while returning only a subset of those records, e.g.:
SELECT DENSE_RANK() OVER(ORDER BY SomeField DESC) SomeRank
What is the best way to do the same thing in MongoDB?
After some experimentation, I found that it is possible to build a ranking function based on MapReduce, assuming the result set can fit in the max document size.
For example, suppose I have a collection like this:
{ player: "joe", points: 1000, foo: 10, bar: 20, bang: "some text" }
{ player: "susan", points: 2000, foo: 10, bar: 20, bang: "some text" }
{ player: "joe", points: 1500, foo: 10, bar: 20, bang: "some text" }
{ player: "ben", points: 500, foo: 10, bar: 20, bang: "some text" }
...
I can perform the rough equivalent of a DENSE_RANK like so:
var m = function() {
++g_counter;
if ((this.player == "joe") && (g_scores.length != g_fake_limit)) {
g_scores.push({
player: this.player,
points: this.points,
foo: this.foo,
bar: this.bar,
bang: this.bang,
rank: g_counter
});
}
if (g_counter == g_final)
{
emit(this._id, g_counter);
}
}}
var r = function (k, v) { }
var f = function(k, v) { return g_scores; }
var test_mapreduce = function (limit) {
var total_scores = db.scores.count();
return db.scores.mapReduce(m, r, {
out: { inline: 1 },
sort: { points: -1 },
finalize: f,
limit: total_scores,
verbose: true,
scope: {
g_counter: 0,
g_final: total_scores,
g_fake_limit: limit,
g_scores:[]
}
}).results[0].value;
}
For comparison, here is the "naive" approach mentioned elsewhere:
var test_naive = function(limit) {
var cursor = db.scores.find({player: "joe"}).limit(limit).sort({points: -1});
var scores = [];
cursor.forEach(function(score) {
score.rank = db.scores.count({points: {"$gt": score.points}}) + 1;
scores.push(score);
});
return scores;
}
I benchmarked both approaches on a single instance of MongoDB 1.8.2 using the following code:
var rand = function(max) {
return Math.floor(Math.random() * max);
}
var create_score = function() {
var names = ["joe", "ben", "susan", "kevin", "lucy"]
return { player: names[rand(names.length)], points: rand(1000000), foo: 10, bar: 20, bang: "some kind of example text"};
}
var init_collection = function(total_records) {
db.scores.drop();
for (var i = 0; i != total_records; ++i) {
db.scores.insert(create_score());
}
db.scores.createIndex({points: -1})
}
var benchmark = function(test, count, limit) {
init_collection(count);
var durations = [];
for (var i = 0; i != 5; ++i) {
var start = new Date;
result = test(limit)
var stop = new Date;
durations.push(stop - start);
}
db.scores.drop();
return durations;
}
While MapReduce was faster than I expected, the naive approach blew it out of the water for larger collection sizes, especially once the cache was warmed up:
> benchmark(test_naive, 1000, 50);
[ 22, 16, 17, 16, 17 ]
> benchmark(test_mapreduce, 1000, 50);
[ 16, 15, 14, 11, 14 ]
>
> benchmark(test_naive, 10000, 50);
[ 56, 16, 17, 16, 17 ]
> benchmark(test_mapreduce, 10000, 50);
[ 154, 109, 116, 109, 109 ]
>
> benchmark(test_naive, 100000, 50);
[ 492, 15, 18, 17, 16 ]
> benchmark(test_mapreduce, 100000, 50);
[ 1595, 1071, 1099, 1108, 1070 ]
>
> benchmark(test_naive, 1000000, 50);
[ 6600, 16, 15, 16, 24 ]
> benchmark(test_mapreduce, 1000000, 50);
[ 17405, 10725, 10768, 10779, 11113 ]
So for now, it looks like the naive approach is the way to go, although I'll be interested to see if the story changes later this year as the MongoDB team continues improving MapReduce performance.
If your score field is directly in your documents, the dense rank is simply the index of the documents in a certain sorted order.
Suppose you have a collection of scores for a game, like:
{user: "dcrosta", score: 10}
{user: "someone", score: 18}
{user: "another", score: 5}
...
Then (assuming you have an index on score) to get ranks you can just query sorted by score (shown here in pymongo syntax):
scores = db.scores.find().sort('score', pymongo.DESCENDING)
for rank, record in enumerate(scores, start=1):
print rank, record['user']
# prints
1 someone
2 dcrosta
3 another
If you're unfamiliar with Python, the enumerate function creates an iterator which returns pairs of (index, element).
EDIT: I assumed you wanted a ranking table -- if you're looking for the rank of a particular user, Richard's answer, or something like it, is what you want.

cocos2d slot machine animation

I am trying to create an application that simulates a slot machine.
Now, I have all the images ready, with the vertical png file and the plist file. My question is, how do I simulate the spinning (when the user presses a button), and then the stopping of the slot machine (after around 1-2 seconds)?
Note that the png file has to wrap around somehow.
Everything else is all a matter of NSArrays and checking, what I want to figure out is the animation. I hope some can share some code or references to do this.
Thanks!
This is relatively straightforward: just repeat the png file as many times as you need to simulate the spinning action. So it's basically a vertical variation on parallax scrolling. If you have Steffan Itterheim's book, he talks about this type of thing in chapter 7 "Scrolling With Joy". You may also find some help here: Cocos2D vertically scrolling background
Hope this helps!
Mike
I am doing something like this:
#include <ctime>
#include <vector>
#include <cstdlib>
#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
using namespace std;
static int last[5]={0, 0, 0, 0, 0};
static int stops[5];
static int reels[5][63] = {
{9,7,12,5,7,3,4,11,9,7,12,6,7,4,11,10,4,3,11,12,7,5,10,9,7,5,9,10,8,9,7,4,9,10,11,5,10,3,9,10,3,9,4,8,7,5,11,9,12,6,3,5,7,9,11,10,6,7,3,5,10,8,4,},
{11,5,4,7,6,8,4,9,7,8,3,11,6,5,11,7,12,5,8,6,10,9,5,6,8,7,12,11,5,6,10,3,4,5,9,12,8,9,6,5,12,8,9,12,7,8,5,10,12,7,11,3,4,8,7,4,5,9,8,6,12,4,6,},
{10,4,5,8,6,7,5,9,6,7,8,4,6,5,11,3,9,8,7,11,12,6,8,5,4,8,6,12,9,6,5,11,3,7,4,8,7,3,10,9,5,6,4,3,9,12,10,8,9,6,3,9,10,6,7,5,6,8,4,11,9,7,8,},
{9,3,6,5,3,10,6,9,5,12,4,8,11,10,7,6,5,9,7,3,8,6,12,4,5,7,3,12,10,6,9,7,8,5,6,4,9,6,11,5,8,12,6,7,3,6,10,3,7,5,10,8,9,6,12,4,7,9,5,6,8,3,10,},
{5,3,9,4,6,12,10,5,11,4,8,7,10,5,9,11,4,6,7,3,6,4,8,5,11,8,5,10,8,11,5,10,8,3,7,4,10,11,5,7,8,9,5,11,6,8,10,3,7,9,3,8,10,12,6,8,10,11,7,10,8,11,6,},
};
static SDL_Window *window = NULL;
static SDL_Surface *canvas = NULL;
static const SDL_Surface *backgroundSurface = IMG_Load("./Background.png");
static SDL_Rect backgroundCoordinates = { 0, 0, 0, 0 };
static const SDL_Surface *symbolsSurface[] = {
NULL,
NULL,
NULL,
IMG_Load("./Symbol03.png"),
IMG_Load("./Symbol04.png"),
IMG_Load("./Symbol05.png"),
IMG_Load("./Symbol06.png"),
IMG_Load("./Symbol07.png"),
IMG_Load("./Symbol08.png"),
IMG_Load("./Symbol09.png"),
IMG_Load("./Symbol10.png"),
IMG_Load("./Symbol11.png"),
IMG_Load("./Symbol12.png"),
NULL,
NULL,
NULL,
NULL,
};
static const SDL_Surface *reelsSurface[5] = {NULL, NULL, NULL, NULL, NULL};
static SDL_Rect symbolsCoordinates[5][3] = {
{ { 298, 118, 0, 0 }, { 298, 266, 0, 0 }, { 298, 414, 0, 0 } },
{ { 474, 118, 0, 0 }, { 474, 266, 0, 0 }, { 474, 414, 0, 0 } },
{ { 651, 118, 0, 0 }, { 651, 266, 0, 0 }, { 651, 414, 0, 0 } },
{ { 827, 118, 0, 0 }, { 827, 266, 0, 0 }, { 827, 414, 0, 0 } },
{ { 1003, 118, 0, 0 }, { 1003, 266, 0, 0 }, {1003, 414, 0, 0 } },
};
static unsigned long animationStart = 0;
static unsigned long animationEnd = 0;
static bool stopped[5] = {false, false, false, false, false};
void draw() {
static double y0 = 0;
static double v0[5] = {-9.5, -9.6, -9.7, -9.8, -9.9};
static long t = 0;
static double a = 0.0005;
static int y = 0;
SDL_BlitSurface((SDL_Surface*) backgroundSurface, NULL, canvas, &backgroundCoordinates);
for (int i = 0; i < 5 && animationStart!=animationEnd; i++) {
/*
* y = y0 + v0*t + 1/2*at^2
*/
y0 = last[i] * 140;
t = (1000 * clock() / CLOCKS_PER_SEC) - animationStart;
y = (int)(y0 + v0[i]*t + a*t*t/2) % (63*140);
if(y < 0) {
y += 63*140;
}
/*
* Stop near to the target position.
*/
if(i==0 && abs(y-stops[i]*140)<=140) {
last[i] = stops[i];
stopped[i] = true;
}else if(stopped[i-1] == true && stopped[i] == false && abs(y-stops[i]*140)<=140) {
last[i] = stops[i];
stopped[i] = true;
}
if(stopped[i] == true) {
SDL_SetSurfaceAlphaMod((SDL_Surface*) reelsSurface[i], 255);
y = stops[i] * 140;
} else {
SDL_SetSurfaceAlphaMod((SDL_Surface*) reelsSurface[i], 191);
}
const SDL_Rect frame = {0, y, 140, 3*140};
SDL_BlitSurface((SDL_Surface*) reelsSurface[i], &frame, canvas, &symbolsCoordinates[i][0]);
}
SDL_UpdateWindowSurface(window);
}
int main() {
SDL_Init(SDL_INIT_EVERYTHING);
/*
* Build long strips (two more images at the end).
*/
for(int i=0, index; i<5; i++) {
reelsSurface[i] = IMG_Load("./Reel.png");
for(int j=0; j<(63+2); j++) {
index = reels[i][j%63];
SDL_Rect coordinates = {0, 140*j, 0, 0};
SDL_BlitSurface((SDL_Surface*) symbolsSurface[index], NULL, (SDL_Surface*)reelsSurface[i], &coordinates);
}
}
//window = SDL_CreateWindow("Slot Reels Animation", 0, 0, 1280, 1024, SDL_WINDOW_FULLSCREEN_DESKTOP);
window = SDL_CreateWindow("Slot Reels Animation", 0, 0, 1440, 900, 0);
canvas = SDL_GetWindowSurface(window);
SDL_Event event;
bool done = false;
while (done == false) {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
done = true;
break;
case SDL_KEYDOWN:
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
done = true;
break;
case SDLK_RETURN:
//startAnimation();
memset(stopped, false, 5*sizeof(bool));
animationStart = 1000 * clock() / CLOCKS_PER_SEC;
for (int i = 0, r; i < 5; i++) {
stops[i] = rand() % 63;
}
break;
}
}
}
draw();
}
SDL_DestroyWindow(window);
for(int i=0; i<5; i++) {
SDL_FreeSurface((SDL_Surface*)reelsSurface[i]);
}
SDL_Quit();
return EXIT_SUCCESS;
}