/* built with Studio Sketchpad:
* https://sketchpad.cc
*
* observe the evolution of this sketch:
* https://studio.sketchpad.cc/sp/pad/view/ro.LnB5YbzqOMx/rev.6934
*
* authors:
* Jared Counts
*
*
* license (unless otherwise specified):
* creative commons attribution-share alike 3.0 license.
* https://creativecommons.org/licenses/by-sa/3.0/
*/
/* Author's notes
I need tabs!
*/
int tileWidth = 48;
boolean [][] map = new boolean[640/tileWidth][480/tileWidth];
Character player;
void setup () { // this is run once.
size(640,480);
player = new Character();
genMap();
for (int i = 0; i < keys.length; i++)
keys[i] = false;
}
void draw () { // this is run repeatedly.
background(255);
stroke(0);
fill(0);
// Render tiles
for (int x = 0; x < map.length; x++) {
for (int y = 0; y < map[x].length; y++) {
if (map[x][y])
rect(x*tileWidth, y*tileWidth, tileWidth, tileWidth);
}
}
// Player
player.updatePosition();
player.solveConstraints();
player.draw();
}
class Character {
float x, y;
float lastX, lastY;
float vX, vY;
boolean touchingFloor = false;
int charWidth = 30, charHeight = 30;
Character () {
x = width/2;
y = 50;
}
void draw () {
stroke(0,255,0);
fill(255,0,0);
rect(x,y, charWidth, charHeight);
lastX = x;
lastY = y;
}
void updatePosition () {
// Gravity
vY += 1.5;
// Move the player if user is pressing keys
if (checkKey(87) && touchingFloor) { // w
vY -= 50;
touchingFloor = false;
}
// if (checkKey(83)) // s
// vY += 2.5;
if (checkKey(65)) // a
vX -= 2.5;
else if (checkKey(68)) // d
vX += 2.5;
else
vX *= 0.7;
// Cap vX and vY
vX = min(vX, 8);
vX = max(vX, -8);
vY = min(vY, 15);
vY = max(vY, -15);
x += vX;
y += vY;
vX *= 0.95;
vY *= 0.95;
}
void solveConstraints () {
touchingFloor = false;
if (x < 1)
x = 1;
if (y < 1)
y = 1;
if (x > width-charWidth-1)
x = width-charWidth-1;
if (y > height-charWidth-1) {
y = height-charWidth-1;
touchingFloor = true;
}
//loat [] topLeft = correctCollision(x,y, x-lastX, y-lastY);
//x = topLeft[0];
//y = topLeft[1];
//float [] topRight = correctCollision(x+charWidth,y, x-lastX, y-lastY);
//x = topRight[0]-charWidth;
//y = topRight[1];
//float [] bottomRight = correctCollision(x+charWidth,y+charWidth, x-lastX, y-lastY);
//x = bottomRight[0]-charWidth;
//y = bottomRight[1]-charWidth;
//float [] bottomLeft = correctCollision(x,y+charWidth, x-lastX, y-lastY);
//x = bottomLeft[0];
//y = bottomLeft[1]-charWidth;
if (isTileSolid(x + charWidth, y)) // right
x = tileToX(xToTile(x + charWidth)) - charWidth - 1;
if (isTileSolid(x, y)) // left
x = tileToX(xToTile(x)) + tileWidth + 1;
if (isTileSolid(x, y)) // top left
y = tileToY(yToTile(y)) + tileWidth + 1;
if (isTileSolid(x + charWidth, y)) // top right
y = tileToY(yToTile(y)) + tileWidth + 1;
if (isTileSolid(x, y + charWidth)) { // bottom left
y = tileToY(yToTile(y + charWidth)) - charWidth - 1;
touchingFloor = true;
}
if (isTileSolid(x + charWidth, y + charWidth)) { // bottom right
y = tileToY(yToTile(y + charWidth)) - charWidth - 1;
touchingFloor = true;
}
}
}
// Taken from http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry2
float [] solveCollision(float lineAX1, float lineAY1, float lineAX2, float lineAY2,
float lineBX1, float lineBY1, float lineBX2, float lineBY2) {
float A1 = lineAY2 - lineAY1;
float B1 = lineAX2 - lineAX1;
float C1 = A1 * lineAX1 + B1 * lineAY1;
float A2 = lineBY2 - lineBY1;
float B2 = lineBX2 - lineBX1;
float C2 = A1 * lineBX1 + B1 * lineBY1;
float det = A1 * B2 - A2 * B1;
if (det == 0)
return new float[] { lineAX1, lineAY1 };
return new float[] { (B2 * C1 - B1 * C2) / det, (A1 * C2 - A2 * C1) / det };
}
// Line Segment Intersection
// http://wiki.processing.org/w/Line-Line_intersection
float [] segIntersection(float lineAX1, float lineAY1, float lineAX2, float lineAY2,
float lineBX1, float lineBY1, float lineBX2, float lineBY2) {
float bx = b.x - a.x;
float by = b.y - a.y;
float dx = d.x - c.x;
float dy = d.y - c.y;
float b_dot_d_perp = bx * dy - by * dx;
if(b_dot_d_perp == 0) {
return null;
}
float cx = c.x - a.x;
float cy = c.y - a.y;
float t = (cx * dy - cy * dx) / b_dot_d_perp;
if(t < 0 || t > 1) {
return null;
}
float u = (cx * by - cy * bx) / b_dot_d_perp;
if(u < 0 || u > 1) {
return null;
}
return new PVector(a.x+t*bx, a.y+t*by);
}
float [] correctCollision (float x, float y, float vX, float vY) {
if (isTileSolid(x, y)) {
float tileX;
float tileY;
if (vX < 0)
tileX = tileToX(xToTile(x)) + tileWidth;
else
tileX = tileToX(xToTile(x));
if (vY < 0)
tileY = tileToY(yToTile(y)) + tileWidth;
else
tileY = tileToY(yToTile(y));
stroke(255,0,0);
noFill();
strokeWeight(3);
line(tileX, 0, tileX, height);
line(0, tileY, width, tileY);
strokeWeight(1);
// Use y = mx + b to step back
// first find m
float m;
if (vX != 0)
m = vY / vX;
else
m = 0; // close enough!
m *= -1;
// find b
float b = y - m * x;
fill(255,0,0);
ellipse(x,y,3,3);
if (abs(x - tileX) < abs(y - tileY)) { // Use x if it's closer to the side than y
x = tileX;
y = m * x + b;
}
else {
y = tileY;
x = (y - b) / m;
}
fill(0,255,0);
ellipse(x,y,4,4);
}
return new float [] {x,y};
}
/* Map methods */
// check to see if tile is solid
boolean isTileSolid (float x, float y) {
// first we find its coordinate in the array
int tileX = xToTile(x);
int tileY = yToTile(y);
// next we see if it is within the array's range
if (tileX >= 0 && tileX < map.length && tileY >= 0 && tileY < map[0].length)
return map[tileX][tileY]; // return whether it's solid or not
return false;
}
int xToTile (float x) {
return floor(x / (float)tileWidth);
}
int yToTile (float y) {
return floor(y / (float)tileWidth);
}
int tileToX (int x) {
return x * tileWidth;
}
int tileToY (int y) {
return y * tileWidth;
}
// generate a random map
void genMap () {
for (int x = 0; x < map.length; x++) {
for (int y = map[x].length/2; y < map[x].length; y++) {
if (random(1) > 0.5)
map[x][y] = true;
else
map[x][y] = false;
}
}
map[xToTile(player.x)][yToTile(player.y)] = false;
}
/* Multikey, inspired by http://wiki.processing.org/w/Multiple_key_presses */
boolean [] keys = new boolean [526];
boolean checkKey (int k) {
return keys[k];
}
void keyPressed () {
// println(keyCode + " was pressed");
keys[keyCode] = true;
}
void keyReleased () {
keys[keyCode] = false;
}