I have a Sketch in Processing written in P5.js, but I don't know how to implement user's input.
The program needs to get .jpg image and it's working on it.
Every my attempt of user-input implementation ends with blank screen or endless "Loading..." screen.
Below is example with preloaded image (I need user to do it).
let img;
let size;
let pixels = [];
function preload(){
img=loadImage('image.jpg');
}
function setup() {
img.resize(windowHeight,0);
size = img.height/2;
createCanvas(img.width, img.height);
background(0);
makePixels();
drawPortrait();
}
function makePixels(){
for(let y=0; y<height; y+=size){
for(let x=0; x<width; x+=size){
let c = img.get(x,y);
tint(c);
pixels.push ( new Pixel (x,y,size,c) );
}
}
}
function drawPortrait(){
for(let p of pixels){
p.show();
}
}
function drawLastFour(){
for(let i = pixels.length-4; i<pixels.length; i++){
pixels[i].show();
}
}
function mouseMoved(){
for(let i = 0; i<pixels.length; i++){
if( (mouseX > pixels[i].x) && (mouseX <= pixels[i].x+pixels[i].s) && (mouseY > pixels[i].y) && (mouseY <= pixels[i].y+pixels[i].s) ){
for(let py = pixels[i].y; py<pixels[i].y+pixels[i].s; py+=pixels[i].s/2){
for(let px = pixels[i].x; px<pixels[i].x+pixels[i].s; px+=pixels[i].s/2){
let c = img.get(px, py);
pixels.push( new Pixel(px,py,pixels[i].s/2, c) );
}
}
pixels.splice(i,1);
break;
}
}
drawLastFour();
}
You can use the createFileInput function to create an input element of type file. Your user can then select an image file, which can be used by your sketch. Here is the (slightly modified) example code that shows how you can use it:
let inputElement;
let userImage;
function setup() {
inputElement = createFileInput(handleFile);
inputElement.position(0, 0);
}
function draw() {
background(255);
if (userImage != null) {
image(userImage, 0, 0, width, height);
}
}
function handleFile(file) {
print(file);
if (file.type === 'image') {
userImage = createImg(file.data, '');
userImage.hide();
} else {
userImage = null;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
I am currently working on a game in Processing and I have split it up into 3 parts so far. The start screen, the level selection screen, and the game screen. The start screen seems to be working fine but when the user gets to the level selection screen it only checks for an if statement once and then stops. Here is the relevant code:
int level = 0;
Player myPlayer;
Floor[] level1Floors = new Floor[5];
Selector levelSelector1;
Selector levelSelector2;
Selector levelSelector3;
Selector levelSelector4;
Selector levelSelector5;
Selector levelSelector6;
Selector levelSelector7;
Selector levelSelector8;
Selector levelSelector9;
Selector levelSelector10;
void setup () {
size(800, 600);
myPlayer = new Player(width/2, 500, 50, 50, 15, 0, 9, true, false, false, false, false);
level1Floors[0] = new Floor(0, 525, width);
level1Floors[1] = new Floor(width, 485, width/2);
startButton = loadImage("playButton.png");
startButtonHover = loadImage("playButtonHover.png");
star = loadImage("Star.png");
starUnlit = loadImage("StarUnlit.png");
levelSelector1 = new Selector(1, 110, 210);
levelSelector2 = new Selector(2, 255, 210);
levelSelector3 = new Selector(3, 400, 210);
levelSelector4 = new Selector(4, 545, 210);
levelSelector5 = new Selector(5, 690, 210);
levelSelector6 = new Selector(6, 110, 390);
levelSelector7 = new Selector(7, 255, 390);
levelSelector8 = new Selector(8, 400, 390);
levelSelector9 = new Selector(9, 545, 390);
levelSelector10 = new Selector(10, 690, 390);
}
void draw () {
if (gamestate == 0) {
startScreen();
}
if (gamestate == 1) {
println("eh");
levelSelection();
levelSelector1.displaySelector();
levelSelector2.displaySelector();
levelSelector3.displaySelector();
levelSelector4.displaySelector();
levelSelector5.displaySelector();
levelSelector6.displaySelector();
levelSelector7.displaySelector();
levelSelector8.displaySelector();
levelSelector9.displaySelector();
levelSelector10.displaySelector();
}
if (gamestate == 2) {
if (level == 1) {
background(54);
level1();
}
}
}
void collision () {
int trueY = myPlayer.y + myPlayer.yOffset;
if (trueY > level1Floors[0].y) {
myPlayer.y = level1Floors[0].y - myPlayer.yOffset;
myPlayer.yvel = 0;
myPlayer.flag = false;
}else {
myPlayer.yvel++;
}
}
void keyPressed () {
if (key == ' ' && !myPlayer.flag && gamestate == 2) {
myPlayer.isJump = true;
}
if (key == 'a' && myPlayer.left == false && gamestate == 2) {
myPlayer.left = true;
}
if (key == 'd' && myPlayer.right == false && gamestate == 2) {
myPlayer.right = true;
}
if (key == 'g') {
exit();
}
}
void keyReleased () {
if (key == ' ') {
myPlayer.isJump = false;
}
if (key == 'a') {
myPlayer.left = false;
}
if (key == 'd') {
myPlayer.right = false;
}
}
class Floor {
int x1;
int y;
int x2;
Floor (int tempX1, int tempY, int tempX2) {
x1 = tempX1;
y = tempY;
x2 = tempX2;
}
void display () {
strokeWeight(3);
line(x1, y, x2, y);
}
}
------------- this code is in a different tab ----------------
PImage star;
PImage starUnlit;
int starSize = 75;
void levelSelection () {
background(130);
}
class Selector {
int value;
int x;
int y;
int sizeX;
int sizeY;
int radius;
int fillValue;
int strokeValue;
Selector(int tempVal, int tempX, int tempY) {
value = tempVal;
x = tempX;
y = tempY;
sizeX = 120;
sizeY = 120;
radius = 20;
fillValue = 70;
strokeValue = 55;
}
void displaySelector () {
fill(fillValue);
stroke(strokeValue);
strokeWeight(6);
rectMode(CENTER);
rect(x, y, sizeX, sizeY, radius);
fill(255);
textSize(40);
textAlign(CENTER,CENTER);
text(value, x, (y-20));
imageMode(CENTER);
image(starUnlit, (x - 30), (y + 20), starSize, starSize);
image(starUnlit, x, (y + 30), starSize, starSize);
image(starUnlit, (x + 30), (y + 20), starSize, starSize);
if (mouseX > (x - 60) && mouseX < (x + 60) && mouseY > (y - 60) && mouseY < (y + 60)) {
println("wow ur computer is a potato");
sizeX = 130;
sizeY = 130;
fillValue = 90;
strokeValue = 75;
}else {
println("u succ");
sizeX = 120;
sizeY = 120;
fillValue = 70;
strokeValue = 55;
}
if (mouseX > (x - 60) && mouseX < (x + 60) && mouseY > (y - 60) && mouseY < (y + 60) && mousePressed) {
gamestate = 2;
level = value;
}
}
}
------------ this is also in a different tab idk if it is relevant though ---------------
PImage startButton;
PImage startButtonHover;
int startButtonx = 400;
int startButtony = 350;
void startScreen () {
background(130);
imageMode(CENTER);
image(startButton, startButtonx, startButtony, 100, 100);
textAlign(CENTER,CENTER);
textSize(60);
text("OBJECTIVE: BREAK OUT", width/2, height/6);
if (dist(mouseX, mouseY, startButtonx, startButtony) < 43) {
imageMode(CENTER);
image(startButtonHover, startButtonx, startButtony, 110, 110);
}
if (dist(mouseX, mouseY, startButtonx, startButtony) < 43 && mousePressed) {
gamestate = 1;
}
}
void level1 () {
background(54);
myPlayer.display();
level1Floors[0].display();
level1Floors[1].display();
collision();
myPlayer.jump();
}
class Player {
int x;
int y;
int vSide;
int hSide;
int yOffset;
int speed;
int yvel;
int xvel;
boolean isCollide;
boolean isJump;
boolean right;
boolean left;
boolean flag;
Player (int tempX, int tempY, int tempVSide, int tempHSide, int tempSpeed, int tempyvel, int tempxvel, boolean tempIsCollide, boolean tempIsJump, boolean tempRight, boolean tempLeft, boolean tempFlag) {
x = tempX;
y = tempY;
vSide = tempVSide;
hSide = tempHSide;
speed = tempSpeed;
yvel = tempyvel;
xvel = tempxvel;
isCollide = tempIsCollide;
isJump = tempIsJump;
right = tempRight;
left = tempLeft;
flag = tempFlag;
yOffset = 25;
}
void display() {
fill(0);
strokeWeight(2);
stroke(255);
rectMode(CENTER);
rect(x, y, hSide, vSide);
y += yvel;
}
void jump () {
if (isJump) {
y -= 20;
flag = true;
}
if (left && x >= 25) {
x -= xvel;
}
if (right && x <= (width - 25)) {
x += xvel;
}
}
}
I know the code is pretty disorganized and Im planning on fixing the problem later. The problem lies in the Selector class if I am correct as that is where the 2 if statements are that don't keep checking if the condition is met. Any help would be appreciated, thank you for your time.
Your problem was harder to diagnose than it looks. As you had guesses, there is a problem in the level selection screen. But the problem is also in the startScreen() method, and the symptom you can see, the "freeze", is a consequence of these things in relation with the level selection logic implemented.
It took me some time to see the problem because at first it missed a lot of functions, and even later I still didn't have the images, so I had to tweak the code to see stuff, which made me this half guesswork and half analysis.
You may wonder why I'm saying all these things. There's a good reason: I want you to be able to ask your next question in a manner which will help people to answer it. If you had asked a question about a specific functionality, it would have been easy enough, but this is debugging. To debug code without being to run it is much harder than it could. That's why I told you about posting a Minimal, Reproducible Example. If you need help with a bug, being able to reproduce it is a powerful tool for those who willing to help. That I have been the only one to answer may be linked to this deficiency.
The problem is mousePressed. If you read a little bit on it in the the Processing documentation, you'll see this: "The mousePressed variable stores whether or not a mouse button is currently being pressed".
This also means that the mousePressed will be true as long as a mouse button is down. The user can click on a random spot, keep the button down and drag the mouse toward a level selector and it will register in your code as if he had clicked on this level.
Here's what happens:
In the startScreen(), the user clicks on the image to start.
The gamestate goes into "level selection" faster than the eye can see, and waaay faster than the finger on the mouse can release the button.
The level selector which appears right where the mouse is registers this as a click.
The gamestate change to "2", but the level the user choose by mistake isn't available yet. The game seems to freeze because it's stuck there.
As you can see, you have to figure out a way to differentiate "holding a button down" and the user actually clicking on something. For now this is just a small glitch, but as you build on this program it'll become a problem increasingly frustrating.
There are many, many ways to deal with this. I'll give you code for one of them which I think is simple and efficient. Still, if you are ambitious enough, to create a class which only exists to manage the user inputs would be a cleaner and better structured way to do this.
But let's take the easy road for now (step by step for clarity):
Add this global variable:
boolean leftMouseButtonClicked = false;
It will replace the problematic mousePressed later.
Add this method to your project:
void mouseClicked() {
if (mouseButton == LEFT) {
leftMouseButtonClicked = true;
}
}
This will turn on the boolean we added in point 1 when the user click then releases the LEFT mouse button. mouseClicked is a built in Processing function. You can read more about it here.
Change your draw() method for this one:
void draw () {
switch (gamestate) {
case 0:
startScreen();
break;
case 1:
levelSelection();
levelSelector1.displaySelector();
levelSelector2.displaySelector();
levelSelector3.displaySelector();
levelSelector4.displaySelector();
levelSelector5.displaySelector();
levelSelector6.displaySelector();
levelSelector7.displaySelector();
levelSelector8.displaySelector();
levelSelector9.displaySelector();
levelSelector10.displaySelector();
break;
case 2:
switch (level) {
case 1:
level1();
break;
default:
gamestate = 1;
}
}
leftMouseButtonClicked = false;
}
It's about the same thing, with a couple important changes:
3.1. I took the liberty of using a switch statement instead of the handful of if statements there was before. The switch is easy to read and the cases need to be mutually exclusives for this to work. You could have used the if - else if - else if... form instead, but I like the switch better for readability.
3.2. I added a default case to the level switch, so when you misclick on a level which doesn't exist yet instead of freezing it'll go back to the level selection gamestate.
3.3. I turn off the leftMouseButtonClicked boolean so it doesn't stay "on" all the time.
Change every place where you wrote mousePressed so you use leftMouseButtonClicked instead.
That's all there is to do to correct the situation. I tried not to optimize your code so it stays yours (except for those switch which I couldn't resist). Your code makes sense and is much better structured than a many others. Sure, it could be improved a lot, but that's the kind of stuff that you'll learn while getting better. And I'm confident that you'll be good.
I hope I made everything clear. Good coding and have fun!
So I have a Flash ActionScript 2 code, which creates a preset amount of enemies, gives enemies stats, and makes them move around randomly. Code:
//Settings
var mapWidth:Number = 550;
var mapHeight:Number = 400;
var enemiesArray:Array = new Array();
var totalEnemies:Number;
var eClip:MovieClip;
//Math functions
function getdistance(x, y, x1, y1)
{
run = x1-x;
rise = y1-y;
return (hyp(run, rise));
}
function hyp(a, b)
{
return (Math.sqrt(a*a+b*b));
}
function resetDirection(mc:MovieClip)
{
mc.roamTime = random(50);
mc.t = mc.roamTime;
mc.roamDistance = random(60)+25;
mc.randomRoamDistanceX = (Math.random()*mc.roamDistance)+mc.xx-(mc.roamDistance/2);
mc.randomRoamDistanceY = (Math.random()*mc.roamDistance)+mc.yy-(mc.roamDistance/2);
mc.newRoamDistance = getdistance(mc._x, mc._y, mc.randomRoamDistanceX, mc.randomRoamDistanceY);
mc.norm = mc.roamSpeed/mc.newRoamDistance;
mc.finalRoamDistanceX = (mc.randomRoamDistanceX-mc.xx)*mc.norm;
mc.finalRoamDistanceY = (mc.randomRoamDistanceY-mc.yy)*mc.norm;
}
//function to move enemies
function moveIt(mc:MovieClip)
{
//reduce roamTime;
mc.t--;
//move enemy to new position
if (getdistance(mc._x, mc._y, mc.randomRoamDistanceX, mc.randomRoamDistanceY)>mc.roamSpeed) {
mc._x += mc.finalRoamDistanceX;
mc._y += mc.finalRoamDistanceY;
}
//rotate enemy
XXXdiff = mc.xx-mc.randomRoamDistanceX;
YYYdiff = -(mc.yy-mc.randomRoamDistanceY);
rrradAngle = Math.atan(YYYdiff/XXXdiff);
if (XXXdiff<0) {
cccorrFactor = 270;
} else {
cccorrFactor = 90;
}
//
mc.ship_mc._rotation = -(rrradAngle*360/(2*Math.PI)+cccorrFactor);
//check if time to reset, based on roamTime
if (mc.t<=0) {
resetDirection(mc);
}
}
//
// Generate Enemies
//
// set and save enemy stats
//
//
// createEnemies(number of enemies you want, movieclip where you want to create the enemies);
//
function createEnemies(amount:Number, targetLocation:MovieClip) {
trace("createEnemies: "+amount);
for (var i = 0; i<amount; i++) {
randomXpos = Math.round(Math.random()*mapWidth);
randomYpos = Math.round(Math.random()*mapHeight);
//add new enemy to map
var newEnemy:MovieClip = targetLocation.attachMovie("enemy1", "enemy1_"+i, targetLocation.getNextHighestDepth());
enemiesArray.push(newEnemy);
//
//set enemy stats
newEnemy.id = i;
newEnemy._x = randomXpos;
newEnemy._y = randomYpos;
//save x and y position
newEnemy.xx = newEnemy._x;
newEnemy.yy = newEnemy._y;
//
newEnemy.roamSpeed = 2
newEnemy.roamTime = random(50);
newEnemy.roamDistance = random(60)+25;
newEnemy.t = 0;
//
newEnemy.myHealth = 10;
newEnemy.myName = "Small Scout";
//
resetDirection(newEnemy);
//target enemy
newEnemy.onPress = function() {
trace("Enemy: "+this.tName+" "+this.id);
target_txt.text = this.myName+": "+this.id+" Health: "+this.myHealth;
};
newEnemy.onEnterFrame = function() {
moveIt(this);
};
}
}
start_btn.onRelease = function() {
if (start_txt.text == "Start") {
//run the create enemies function to start the engine
createEnemies(box_mc.numberOfEnemies.text, map_mc);
//hide start button
start_txt._visible =false;
this._visible = false;
box_mc._visible = false;
}
};
I want program enemies to be grouped (based on fireflies algorithm). My idea is write for loop to define attractiveness, but I don't know how to make my objects move to the most attractiveness. Maybe someone would help me with this problem?
I change this line:
newEnemy.myHealth = 10;
on this
newEnemy.myHealth = Math.round(random(9)+1);
myHealth would be responsible for attractiveness. I try to use code from this site and modificate code to let objects with low attractiveness follow objects with large attractiveness. Also, I want to stop algorith, when they are in the groups.
I have almost finished my project, however when I try to load in a movie clip in my library when the score I have reaches 100, it removes the game from the stage, but doesn't show the screen that I am trying to show.
The code I have written is below. Any assistance would be greatly appreciated.
package
{
import flash.display.*;
import flash.events.*;
import flash.text.*;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
public class blast_game extends MovieClip
{
// creates a variable that stores the catcher that
//will be used to collect the chocolate bars.
var catcher:Catcher;
var nextObject:Timer;
var objects:Array = new Array();
var score:int = 0;
const speed:Number = 7.0;
//end of catcher code
//beginning of game code - spawns a new catcher on screen
//at start of game.
public function blast_game()
{
catcher = new Catcher();
catcher.y = 350;
addChild(catcher);
setNextObject();
addEventListener(Event.ENTER_FRAME, moveObjects);
}
//end of catcher spawn
//sets variables for the random object drops,
//increments the objects to appear every second.
public function setNextObject()
{
nextObject = new Timer(1000+Math.random()*1000,1);
nextObject.addEventListener(TimerEvent.TIMER_COMPLETE,newObject);
nextObject.start();
}
//end of object variables
public function newObject(e:Event)
{
//creates an array to hold the "Good" and "Bad" objects in
//the application.
var goodObjects:Array = ["Circle1","Circle2"];
var badObjects:Array = ["Square1","Square2"];
if (Math.random() < .5)
{
//replaces the "good" object when the object hits the floor, places
//object back in array to drop again.
var r:int = Math.floor(Math.random() * goodObjects.length);
var classRef:Class = getDefinitionByName(goodObjects[r]) as Class;
var newObject:MovieClip = new classRef();
newObject.typestr = "good";
//end of "Good" object replacement
}
else
{
//replaces the "Bad" object when the object hits the floor, places
//object back in array to drop again
r = Math.floor(Math.random() * badObjects.length);
classRef = getDefinitionByName(badObjects[r]) as Class;
newObject = new classRef();
newObject.typestr = "bad";
//end of "Bad" object replacement
}
//randomises the location the objects will be placed on stage
//after replacement.
newObject.x = Math.random() * 500;
addChild(newObject);
objects.push(newObject);
setNextObject();
//end of object randomisation
}
public function moveObjects(e:Event)
{
for (var i:int=objects.length-1; i>=0; i--)
{
//code to increase speed of objects over time.
objects[i].y += speed;
if (objects[i].y > 400)
{
removeChild(objects[i]);
objects.splice(i,1);
}
//hit test for catcher - if any object hits the catcher
//increase or decrease score respectively.
if (objects[i].hitTestObject(catcher))
{
//increase score when catcher catches "Good" object
if (objects[i].typestr == "good")
{
score += 10;
}
else
//decrease score if catcher catches "Bad" object.
{
score -= 5;
}
//prevents score from going below 0
if (score < 0)
{
score = 0;
}
scoreDisplay.text = "Score: " + score;
//once object hits catcher, remove object from stage.
removeChild(objects[i]);
objects.splice(i,1);
}
//if statement to move screen to promotion screen
//once score reaches past 100
//THIS IS WHERE I THINK THE ISSUE IS!!!
if(score >= 100) {
var promotionScreen:promotion = new promotion;
//stage.removeChild(this)
addChild(promotionScreen);
removeEventListener(Event.ENTER_FRAME, moveObjects);
promotionScreen = stage.stageWidth / 2;
promotionScreen = stage.stageHeight /2;
}
//end of if statement
}
//sets catcher to work with mouse movement.
catcher.x = mouseX;
}
}
}
You should set break inside, at the end of if(score >= 100) because this condition can be launched a couple of times in your for loop. Also your MovieClip can be stopped, so try .play() or .gotoAndStop()
Oh! and you set promotionScreen = stage.stageWidth/2 while you should promotionScreen.x = stage.stageWidth/2
I call this method on LoadContent() - after loading heightMap texture:
private void setEffect(Texture2D heightMap)
{
m_BasicEffect = new BasicEffect(this.GraphicsDevice);
m_BasicEffect.EnableDefaultLighting();
m_BasicEffect.FogEnabled = true;
m_BasicEffect.FogStart = 300f;
m_BasicEffect.FogEnd = 1000f;
m_BasicEffect.FogColor = Color.Black.ToVector3();
m_BasicEffect.TextureEnabled = true;
m_BasicEffect.World = Matrix.Identity;
m_BasicEffect.Texture = heightMap;
}
Now, if I change the "m_BasicEffect.TextureEnabled = true;" to "m_BasicEffect.TextureEnabled = false;" it works, but the texture (of course) doesn't show.
Draw method looks like this:
public override void Draw(Microsoft.Xna.Framework.GameTime i_GameTime)
{
Matrix worldMatrix = Matrix.CreateTranslation(-m_TerrainWidth / 2.0f, 0, m_TerrainHeight / 2.0f) * Matrix.CreateRotationY(m_Angle);
m_BasicEffect.View = MyCamera.View;
m_BasicEffect.Projection = MyCamera.Projection;
m_BasicEffect.World = worldMatrix;
foreach (EffectPass pass in m_BasicEffect.CurrentTechnique.Passes)
{
pass.Apply();
Game.GraphicsDevice.Indices = myIndexBuffer;
Game.GraphicsDevice.SetVertexBuffer(myVertexBuffer);
Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, m_VerticesNormalLength, 0, m_IndicesLength / 3);
}
}
Moreover, if I try to draw Models afterwords, it throws an exception:
"The current vertex declaration does not include all the elements required by the current vertex shader."
The way I try to draw the Models:
public override void Draw(GameTime i_GameTime)
{
Matrix[] transforms = new Matrix[MyModel.Bones.Count];
MyModel.CopyAbsoluteBoneTransformsTo(transforms);
foreach (ModelMesh mesh in MyModel.Meshes)
{
foreach (BasicEffect be in mesh.Effects)
{
be.EnableDefaultLighting();
be.Projection = MyCamera.Projection;
be.View = MyCamera.View;
be.World = GetWorld() * mesh.ParentBone.Transform;
}
mesh.Draw();
}
}
What do you think about it?
Thanks in advance.