I am making my own version of minesweeper using p5.
Right now, when I click on the bomb cell, I show all the bombs in the given grid.. but the game is still playable. Is there any way to restart the game without reloading the page?
I can produce an alert but that does not do much except say that "game is over", is there any way to restart when I click on OK on that?
You'd want to store the state of your game in some sketch-level variables. Then to reset the game, you'd want to set the variables back to their original values. You might do this in something like a reset() function. Here's a simple example:
var y;
function setup() {
createCanvas(400, 400);
reset();
}
function reset(){
y = 0;
}
function mousePressed(){
reset();
}
function draw() {
background(220);
ellipse(width/2, y, 20, 20);
y++;
}
In your case, you'd probably want to call the reset() function after the user presses the okay button in the dialog.
Related
I am using Processing to create a basketball game. I have managed to create the basketball game but I want to have a click to start home screen. I have made the graphic for the home screen but I am not sure how to integrate it into the game code. Any ideas on how to go about this. Thanks!
I found something on the internet related to this which was...
if (started) {
//all the code for the game
} else {
// all the code for the start screen
if (keyDown("enter")) {
started = true;
}
}
Im not sure if this is leading me in the right direction or how I could necessarily use this.
Use keyPressed() outside the draw().
void keyPressed() {
println(int(key));
if (key==10) {
println("ENTER");
}
}
key - contains the value of the most recent key on the keyboard that was used (either pressed or released).
What is described in: https://processing.org/reference/keyPressed_.html
Here is a little demo program that may help you. The global variable started controls whether the game has begun or not. The function keyPressed sets it to true if you press the ENTER key.
In draw, put your game code in the first if-part and your waiting screen in the second.
boolean started = false;
void draw() {
background(0);
textAlign(CENTER);
if (started) {
// your game code here
text("gameplay", 50, 50);
} else {
// your start/launch screen here
text("waiting...", 50, 50);
}
}
void keyPressed() {
if (keyCode == ENTER) {
started = true;
}
}
I personally don't know how much help I can get in this situation. I was trying to make a Flappy bird sketch off of Daniel Shiffman's videos using the p5.js web editor, however when the keyPressed() function was used (which I am familiar with because I did a bunch with Processing), I would get no response. Now originally, it was if(key === ' ') { that was being used, and when the space bar was pressed, the sketch would reset. However, when I tried with other letters, then eventually to just the keyPressed example from the reference, it still wouldn't do anything. It even worked on the website's example, however it wouldn't work in the web editor. What is happening?
Example code:
let value = 0;
function draw() {
fill(value);
rect(25, 25, 50, 50);
}
function keyPressed() {
if (value === 0) {
value = 255;
} else {
value = 0;
}
}
Try this:
//in the draw function
if (keyIsDown(LEFT_ARROW /*or what ever*/)) {
//action
}
I am trying to make a calculator in processing. My thought process for how this is going to work is to make a function for if a certain number is pressed on the keyboard. So I would create some sort of for loop or array even that would sense when a number is pressed, and then return true if it goes through the if statements, however, in order for this to work, I would need to put a variable in the place of a specific key on the keyboard. Is this possible?
Code (so far):
void setup() {
size(800,600);
}
void draw() {
background(0);
Nums.create();
}
class Nums {
void create() {
for (int i = 0; i < 9; i++) {
zero(i);
}
}
boolean zero(int amnt) {
if (keyPressed) {
if (key == amnt) {
return true;
} else {
return false;
}
}
}
}
They keyPressed variable and the functions like keyPressed() and keyReleased() are specifically for keyboard input. They don't, and shouldn't, be concerned with on-screen buttons that you click with the mouse.
Instead, you should probably use the mousePressed() function to detect when the mouse is clicked, and then use if statements to figure out which button was clicked. You can use point-rectangle collision detection to detect which button was clicked. There's also a button sketch in the examples that come with the Processing editor.
I am trying to use g4p-controls library in Processing to create a button that executes a drawing command in another window. In this library, a child window is created by the code
GWindow window = GWindow.getWindow(this, "Main", 100, 50, 500, 500, JAVA2D);
where this is the main applet, and the other arguments specify the name, position, and renderer.
GWindow is a subclass of PApplet, so I should feasibly be able to call a drawing command, for example window.background(0);, from anywhere in my code to paint that window black. However, this does not work, and I cannot figure out why. After all, the same code works when I put it in a handler function and add it to the window:
window.addDrawHandler(this, "windowDraw");
where the windowDraw method is
public void windowDraw(PApplet app, GWinData data) {
app.background(0);
}
Looking into the source code, the draw handler method windowDraw is invoked by the GWindow object with the first argument this, which is exactly the object referred to when I attempted window.background(0);. So window should be the object whose background() method is called to paint the canvas black.
If I am misunderstanding something fundamental about event-driven programming, please let me know. It does seem like the handlers take the relevant applet as an argument for a reason, but I really cannot see what's different about invocation inside and outside the handler functions.
Some additional notes: calling window.background(0); works if it's inside the main draw() function. It does not work if it's in the setup() function, and unfortunately for me, it doesn't work if it's in a button handler method:
public void handleButtonEvents(GButton button, GEvent event) {
if (this.button == button) {
if (event == GEvent.PRESSED) {
window.background(0);
}
}
}
Obviously, I have made sure this code actually runs when I press the button.
Even more strangely, if I substitute the above drawing call to window with something like window.strokeWeight(10), the change actually takes place, and subsequent lines in that canvas are drawn thicker. It only fails to actually draw things. I am just at a loss.
In the future, please try to post a MCVE instead of a bunch of disconnected code snippets. Here's an example:
import g4p_controls.*;
GWindow window;
void setup(){
window = GWindow.getWindow(this, "Main", 100, 50, 500, 500, JAVA2D);
}
void draw(){
background(255, 0, 0);
window.ellipse(mouseX, mouseY, 25, 25);
window.draw();
}
void mousePressed(){
window.background(0, 255, 0);
}
I would expect this code to draw circles in the second window, and to draw green in the second window when I press the mouse in the first window. However, it seems to only draw those things very sporadically.
In fact, here's the same type of program, in "pure Processing" without using the G4P library:
SecondApplet sa;
void setup() {
String[] args = {"TwoFrameTest"};
sa = new SecondApplet();
PApplet.runSketch(args, sa);
}
void settings() {
size(200, 200);
}
void draw() {
background(0);
sa.ellipse(mouseX, mouseY, 25, 25);
}
void mousePressed() {
sa.background(255, 0, 0);
}
public class SecondApplet extends PApplet {
public void settings() {
size(200, 200);
}
void draw() {
}
}
I would also expect this to work, but we see a similar gray window for the second sketch. I've filed a bug here to get feedback from the Processing devs about whether this is expected behavior.
In the meantime, you'll have better luck if you do something like this:
SecondApplet sa;
float drawMouseX;
float drawMouseY;
color drawBackground = #0000ff;
void setup() {
String[] args = {"TwoFrameTest"};
sa = new SecondApplet();
PApplet.runSketch(args, sa);
}
void settings() {
size(200, 200);
}
void draw() {
background(0);
drawMouseX = mouseX;
drawMouseY = mouseY;
}
void mousePressed() {
drawBackground = #00ff00;
}
public class SecondApplet extends PApplet {
public void settings() {
size(200, 200);
}
void draw() {
background(drawBackground);
ellipse(drawMouseX, drawMouseY, 25, 25);
}
}
Instead of calling the drawing functions directly, we're now setting some variables that are then used in the second applet's draw() function. There are a bunch of ways to do this, but the idea is the same: just don't call the draw functions directly, and call them from the draw() function instead.
Update: I heard back from Ben Fry (a founder of Processing) and codeanticode (a developer of Processing) on the bug I filed on GitHub, and I understand better now why this doesn't work.
The reason it doesn't work is because each sketch has its own UI thread, which is responsible for drawing and handling events. You can't draw to a sketch from a different thread, otherwise weird things happen. But you're trying to draw to a second sketch from the first sketche's event thread, which is not the second sketch's drawing thread, which is why it doesn't work.
See the bug for a discussion on alternative approaches, but honestly your best bet is probably to go with the approach I outlined of just sharing variables between the sketches.
I'm constructing a custom node editor window in Unity, and I've had a look at various resources such as this one, which uses GUI.Box to construct node windows.
This works great, and I'm able to drag these windows around the way I want, however once I add controls to the GUI.Box, I want them to override the Drag() function I've written.
Here's an example of the issue - When I move the vertical slider up, the entire box drags with it.
Is there a way to fix this behavior using GUI.Box, or should I go back to GUI.Window with its built-in GUI.DragWindow()?
Here's a simplified version of the code I'm using:
EditorMouseInput.cs:
private bool ActionLeftMouseDown()
{
mouseDownNode = editor.GetSelectedNode(Input.current.mousePosition);
if (mouseDownNode == null)
editor.StartMovingEditorCanvas();
else
mouseDownNode.IsSelected = true;
}
BaseNodeEditor.cs:
public BaseNode GetSelectedNode(Vector2 mousePos)
{
foreach (BaseNode node in Nodes)
{
if (node.WindowRect.Contains(mousePos))
return node;
}
return null;
}
public void Drag(Vector2 delta)
{
if (!MoveEditorMode && !ConnectionMode)
{
foreach (BaseNode node in Nodes)
{
node.Drag(delta);
}
}
BaseNode.cs:
public void Drag(Vector2 delta)
{
if (IsSelected)
draggedDistance += delta;
}
The vertical slider is added in the derived JumpNode class. Extract of the helper class that constructs the slider:
Vector2 pos = node.WindowRect.position + rect.position * GridSpacing;
value = GUI.VerticalSlider(new Rect(pos, rect.size * GridSpacing), value, maxValue, minValue);
I can see why this doesn't do what I want, but I don't know how to go about it given the GUI controls aren't part of the GUI.Box.
Any help or suggestions, even a nudge towards another source would be greatly appreciated - I feel I've used all the search terms that exist in my head!
Edit - Solved: Thanks to Kleber for solving this one for me. In case anyone else runs into this or a similar issue, the solution for me was in realising that GUI controls consume left mousedown events automatically, so clicking a slider means there's no propagation to the Box to check if it was clicked.
What I needed to do was separate the IsSelected and IsDragged flags in the Node class, and clear IsDragged on mouseUp. I originally used IsSelected to flag both drag enabled, and selected (multiple nodes could be selected and dragged at once).
It's quite a complex tutorial so I didn't read it entirely, but the problem seems to be the MouseDrag detection. Well, basically you want to stop the event propagation when you click on a GUI element inside the Box, right? To do so, you call:
Event.current.Use()
every time the user drags the mouse on one of your components.
Using the resource you've mentioned, I altered the Node class and added a slider inside the Draw() method, ending like this:
public void Draw() {
inPoint.Draw();
outPoint.Draw();
GUI.Box(rect, title, style);
GUI.BeginGroup(rect);
_value = GUI.HorizontalSlider(new Rect(20, 0, 50, 20), _value, 100, -100);
GUI.EndGroup();
}
Another thing you can do is change how you draw your window. Here it's a simple example that I've tested on the latest Unity version (5.6):
private void OnGUI() {
GUI.Box(_rect, string.Empty);
GUI.BeginGroup(_rect);
_value = GUI.VerticalSlider(new Rect(145, 100, 20, 100), _value, 100, -100);
GUI.EndGroup();
var e = Event.current;
if (e.type == EventType.MouseDrag && _rect.Contains(e.mousePosition)) {
_rect.x += e.delta.x;
_rect.y += e.delta.y;
Repaint();
}
}
As you can see, this example doesn't need an Event.current.Use() to work properly.