How to Calculate a particular area using MouseClicked () method in Processing? - arduino

In my window there is a circle. I have implemented the void MouseClicked() method to take effect on the mouse click event. That means only clicking inside the circle should change the color of the circle and do the corresponding operation.
But the problem is wherever I click (even outside the circle), it changes the color of the circle. So I understand that the mouseClicked() method isn't stable. How do I fix this?
My code in processing:
int colorValue = 0;
void setup() {
size(450, 255);
background(204);
}
void draw() {
fill(colorValue);
ellipse(56, 46, 55, 55);
}
void mouseClicked() {
if (colorValue == 0) {
colorValue = 255;
} else {
colorValue = 0;
}
}

You aren't doing any check for whether the mouse is in the circle. You could use the dist() function to help with that:
int colorValue = 0;
float circleX = 56;
float circleY = 46;
float circleR = 55;
void setup() {
size(450, 255);
background(204);
ellipseMode(RADIUS);
}
void draw() {
fill(colorValue);
ellipse(circleX, circleY, circleR, circleR);
}
void mouseClicked() {
if(dist(mouseX, mouseY, circleX, circleY) < circleR){
if (colorValue == 0) {
colorValue = 255;
} else {
colorValue = 0;
}
}
}

Related

Why is the QPushbuttons not interacting with the Slot function

Im trying to create an tic tac toe game, where buttons are used for the positions of where the knaughts and crosses are to be used. When I move the buttons into their respective places, the slot is not triggered and nothing happens.
`
#include "tic_tac_toe.h"
#include <iostream>
tic_tac_toe::tic_tac_toe(QWidget *parent)
: QMainWindow(parent)
{
setFixedSize(900,900);
initBoard();
//showBoard();
connect(button,SIGNAL(clicked()),this,SLOT(buttonpressed()));
}
tic_tac_toe::~tic_tac_toe()
{
}
void tic_tac_toe::initBoard()
{
int x = 0;
int y = 0;
for(int i = 0; i < 10; i++)
{
button = new QPushButton(this);
board.append(button);
button->show();
button->setFixedSize(300,300);
//button->setStyleSheet("border: 5px solid black");
button->setText("??");
// button->move(x,y);
// x = x + 300;
// if(x == 900)
// {
// y = y + 300;
// x = 0;
// }
}
}
void tic_tac_toe::showBoard()
{
}
void tic_tac_toe::buttonpressed()
{
button->setText("X");
}
I tried doing it with only one QPushbutton and it works, however when I move and create more buttons, the Slot function does not work on the buttons.
You only ever connect to the last QPushButton instance created. Move the connect call from the constructor into tic_tac_toe::initBoard and use a lambda to capture the value of button...
void tic_tac_toe::initBoard()
{
for (int i = 0; i < 10; i++) {
button = new QPushButton(this);
board.append(button);
button->show();
button->setFixedSize(300,300);
button->setText("??");
connect(button, &QPushButton::clicked, this,
[this, button]
{
buttonpressed(button);
});
}
}
Likewise, update the signature of tic_tac_toe::buttonpressed...
void tic_tac_toe::buttonpressed (QPushButton *button)
{
button->setText("X");
}

Button for Creative Coding Asteroids project

I'm an undergrad and in one of my classes, we have this assignment to make the Asteroids game (you know, the retro one!) on Processing (which is basically a simplified Javascript program). I have the code for a button:
void setup()
{
size(1280, 720);
}
void draw()
{
background(0,0,0);
drawButton();
}
Boolean pointIsInRectangle(int left, int top, int right, int bottom, int pointX, int pointY)
{
if (pointX >= left
&& pointX <= right
&& pointY <= bottom
&& pointY >= top
)
return true;
else
return false;
}
void drawButton()
{
int left = 350;
int top = 145;
int right = 860;
int bottom = 220;
rectMode(CORNERS);
color background = color(0,0,0);
if (pointIsInRectangle(left,top,right,bottom,mouseX,mouseY))
{
background = color(255);
}
// draw outer rectangle
stroke(255);
fill(background);
rect(left,top,right,bottom);
// draw caption
fill(255);
textSize(100);
text(" ASTEROIDS", left,bottom);
}
and I have the preliminary code for the ship for the game, but I need the button to get to an "in between" page so that when the button is clicked, it leads to a new screen that says "click anywhere to play game" and when any point in the screen is clicked, the ship appears and asteroids begin appearing and the game begins. HOW DO I GET THE BUTTON TO LEAD TO A NEW PAGE, AND HOW DO I CREATE THAT PAGE? I really cannot figure it out. Crossing my fingers that someone will be able to give me some guidance!!!!!
The actual result I'm seeing is that nothing is happening when the button is clicked. This makes sense because I don't know how to add the next page that says Click to Play Game, so this is the issue I'm facing. The code I have so far can be found above.
This is not question about a button, but about a game engine with multiple scenes.
Your game is a collection of screens (scenes). Every scene have definition of visuals, definition of logic, and definition of switch for another scene.
Here is the minimal solution of Your problem.
1 - Define visuals of Your screens in .display() method,
2 - Define logic condition for next screen switch in stateCondition().
boolean mouseReleased;
GameScreen screen;
GameScreen splashScreen;
GameScreen inBetweenPage;
void setup() {
size(1280, 720);
GameScreen splashScreen = new SplashScreen();
GameScreen inBetweenPage = new InBetweenPage();
splashScreen.setNextScreen(inBetweenPage);
inBetweenPage.setNextScreen(splashScreen);
screen = splashScreen;
mouseReleased = false;
}
void draw() {
screen.display();
if (screen.stateCondition()) {
screen = screen.getNextScreen();
}
}
interface GameScreen {
/**
** screen visual definition
**/
void display();
/**
** screen change state condition
**/
boolean stateCondition();
void setNextScreen(GameScreen scr);
GameScreen getNextScreen();
}
class SplashScreen implements GameScreen {
GameScreen nextScreen;
int left = 350;
int top = 145;
int right = 860;
int bottom = 220;
void display() {
background(0, 0, 0);
rectMode(CORNERS);
color background = color(0, 0, 0);
if (pointIsInRectangle(left, top, right, bottom, mouseX, mouseY)) {
background = color(255, 255, 255, 160);
}
// draw outer rectangle
stroke(255);
fill(background);
rect(left, top, right, bottom);
// draw caption
fill(255);
textSize(100);
textAlign(CENTER, CENTER);
text("ASTEROIDS", (left+right)/2, (top+bottom)/2-16);
}
boolean stateCondition() {
if (mouseReleased && (mouseButton == LEFT)) {
mouseReleased = false;
return pointIsInRectangle(left, top, right, bottom, mouseX, mouseY);
}
return false;
}
GameScreen getNextScreen() {
return nextScreen;
}
void setNextScreen(GameScreen target) {
this.nextScreen = target;
}
}
class InBetweenPage implements GameScreen {
GameScreen nextScreen;
int left = 0;
int top = 0;
int right = width;
int bottom = height;
void display() {
background(0, 0, 0);
// draw caption
fill(255);
textSize(24);
textAlign(CENTER, CENTER);
text("< click anywhere to play game >", width/2, height/2);
}
boolean stateCondition() {
if (mouseReleased && (mouseButton == LEFT)) {
mouseReleased = false;
return pointIsInRectangle(left, top, right, bottom, mouseX, mouseY);
}
return false;
}
GameScreen getNextScreen() {
return nextScreen;
}
void setNextScreen(GameScreen target) {
this.nextScreen = target;
}
}
Boolean pointIsInRectangle(int left, int top, int right, int bottom, int pointX, int pointY) {
if (pointX >= left && pointX <= right && pointY <= bottom && pointY >= top) {
return true;
} else
return false;
}
void mouseReleased() {
mouseReleased = true;
}
There is a relatively simple solution to this problem, which would be to make some space for a special "splashscreen" state in your code. It would almost be ninja coding to implement it, although in this case as you are learning it's not taking shortcuts but more like climbing a new step in the learning stairwell. Here's a proof of concept which shows what I'm speaking about:
// this boolean keeps track of the current game state: splashscreen or not
boolean splashScreen = true;
void setup() {
size(600, 400);
}
void draw() {
background(0);
// if the game has yet to start, show the splashscreen
if (splashScreen) {
drawSplashScreen();
} else {
playGame();
}
}
// this method draws the splashScreen
// it could be coded in the 'draw()' method, but it's easier to read this way
void drawSplashScreen() {
textAlign(CENTER);
textSize(30);
fill(255);
text("THIS IS THE SPLASHSCREEN \n click anywhere to play the game", width/2, height/2);
}
// this method contains everything your game loop needs to work
void playGame() {
textAlign(CENTER);
textSize(40);
fill(200, 0, 200);
text("YOU ARE CURRENTLY \n PLAYING THE GAME", width/2, height/2);
}
void mouseClicked() {
if (splashScreen) {
splashScreen = !splashScreen;
}
}
Here you have 2 game states: the splash screen and the game itself, but you could implement more than just these two. There's a design pattern called Finite State Machine that would be just perfect for your needs. Although you already have everything you need to code your assignment, let me explain a little further:
A FSM let you determine the context which can lead to another context and limit some actions to it's own context. A good example of this is Mario in the original Super Mario Bros game: when he's small, getting a magic mushroom will transform him into Super Mario. When he's Super, getting a flower will transform him into Fire Mario. But while small, getting a flower will only make him into Super Mario, not Fire Mario (in the ooold first game at least). That's because each one of these states have rules, and he cannot just jump from one to the other without regard for these.
Your game's logic has it's own rules too: you have the first screen with the "start" button. When this button is clicked, there's a second state where it says "click anywhere to play the game". If the user clicks, then the game itself starts. That makes for 3 states (3 screens if you like) where every state has it's own set of rules - which we often call 'business rules'.
We could schematize this assignment like this:
And here's the skeleton code that would implement such a game, including a bonus rectangle collision detection method:
// the game states are as follow:
// 0 is welcome screen with button
// 1 is click anywhere screen
// 2 is the game itself
int gameState = 0;
void setup() {
size(600, 400);
}
void draw() {
background(0);
// let's use the right game state here
switch(gameState) {
case 0:
drawWelcomeScreen();
break;
case 1:
drawClickAnywhereScreen();
break;
case 2:
playGame();
break;
}
}
void drawWelcomeScreen() {
fill(0, 0, 100);
rect(100, 100, 400, 100);
textAlign(CENTER);
textSize(30);
fill(255);
text("Click here to play", 300, 150);
text("THIS IS THE WELCOME SCREEN", width/2, 50);
}
void drawClickAnywhereScreen() {
textAlign(CENTER);
textSize(30);
fill(255);
text("Click anywhere to play the game", width/2, height/2);
}
void playGame() {
textAlign(CENTER);
textSize(40);
fill(200, 0, 200);
text("YOU ARE CURRENTLY \n PLAYING THE GAME \n click anywhere to go \n back to the welcome screen", width/2, height/2);
}
void mouseClicked() {
// now this will be more complicated, because you'll want to deal with clicks differently depending on the game state
// which kinda answers the question as how we'll deal with this issue: same as in the 'draw()' method
switch(gameState) {
case 0:
// if the click's coordinates are in the rectangle's coordinates (use math here, or a collision method)
// (in fact, use math pretty much everywhere)
// (I hope you like math)
// anyway here's an old collision method I paste everywhere on SO, feel free to steal it and improve on it!
// I wrote it as a student to deal with pretty much the same stuff that you're going through
if (intersect(100, 100, 400, 100, mouseX, mouseY, 1, 1)) {
gameState = 1;
}
break;
case 1:
gameState = 2;
break;
case 2:
gameState = 0;
break;
}
}
// enter the xy coordinates, the width and the heigh of 2 rectangle shapes and it'll return true if they intersect
boolean intersect(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) {
boolean checkX = false;
boolean checkY = false;
if ( (x1<x2 && (x1+w1)>x2) || (x1<(x2+w2) && (x1+w1)>x2+w2) || (x1>x2 && (x1+w1)<(x2+w2)) ) {
checkX = true;
}
if ( (y1<y2 && (y1+h1)>y2) || (y1<(y2+h2) && (y1+h1)>y2+h2) || (y1>y2 && (y1+h1)<(y2+h2)) ) {
checkY = true;
}
return checkX && checkY;
}
I hope I'm not confusing you with all this material. I'll try and keep an eye out for any question you may have about these things.
Good luck and have fun!

Simple boolean on/off button in Processing

I'm trying to write button class, one that would switch between on and off states using boolean function.
Switch should happen after if(mousePressed). I can get it to work one way, but I'm lost while trying to get it to switch back to previous state.
When I change one of the if(mousePressed) to if(keyPressed) everything works just fine.
Thank you for your time good Sir.
bclass button;
int offset = 20;
void setup() {
rectMode(CORNERS);
noStroke();
size(300, 100);
button = new bclass(offset, offset, width-offset, height-offset);
}
void draw() {
button.display();
button.state(mouseX, mouseY);
}
class bclass {
float x;
float y;
float w;
float h;
boolean state = false;
bclass(float x_, float y_, float w_, float h_) {
x = x_;
y = y_;
w = w_;
h = h_;
}
void display() {
if (state) {
fill(255, 0, 0);
} else {
fill(0);
}
rect(x, y, w, h);
}
void state(int mx, int my) {
if (!state) {
if (mousePressed) {
if (mx > x && mx < x + w) {
state = true;
}
}
}
if (state) {
if (mousePressed) {
if (mx > x && mx < x + w) {
state = false;
}
}
}
}
}
Change your state method to:
void state(int mx, int my) {
if (mousePressed) {
if (mx > x && mx < x + w) {
state = !state; // change state to opposite value
delay(100); // delay 100ms (mousePressed lasts some millis)
}
}
}
But better solution will be to use Processing's mouseClicked() event:
public void draw() {
button.display();
}
public void mouseClicked() {
button.state(mouseX, mouseY);
}
class bclass {
...
void state(int mx, int my) {
if (mx > x && mx < x + w) {
state = !state;
}
}
}
In this solution button.state() is called only from mouseClicked(), and mouseClicked() is called by Processing when it discovers such event.

How to use Processing to plot serial data

I'm trying to plot some sensor data that's being read in through the serial port. I found this Processing example code of a 2D plotter, and I'm trying to alter it to work for my application.
The programming is a bit over my head though. I can see that it's getting data for the three lines from the three equation classes. I'd like to replace the part where is reads the mouseX with a variable or something that points to the newest sensor update. The sensor data is continuously updated in the void Draw() loop.
/**
* RollingGraph
* This sketch makes ise of the RollingLine2DTrace object to
* draw a dynamically updated plot.
*/
import org.gwoptics.graphics.graph2D.Graph2D;
import org.gwoptics.graphics.graph2D.traces.ILine2DEquation;
import org.gwoptics.graphics.graph2D.traces.RollingLine2DTrace;
class eq implements ILine2DEquation{
public double computePoint(double x,int pos) {
return mouseX;
}
}
class eq2 implements ILine2DEquation{
public double computePoint(double x,int pos) {
return mouseY;
}
}
class eq3 implements ILine2DEquation{
public double computePoint(double x,int pos) {
if(mousePressed)
return 400;
else
return 0;
}
}
RollingLine2DTrace r,r2,r3;
Graph2D g;
void setup(){
size(600,300);
r = new RollingLine2DTrace(new eq() ,100,0.1f);
r.setTraceColour(0, 255, 0);
r2 = new RollingLine2DTrace(new eq2(),100,0.1f);
r2.setTraceColour(255, 0, 0);
r3 = new RollingLine2DTrace(new eq3(),100,0.1f);
r3.setTraceColour(0, 0, 255);
g = new Graph2D(this, 400, 200, false);
g.setYAxisMax(600);
g.addTrace(r);
g.addTrace(r2);
g.addTrace(r3);
g.position.y = 50;
g.position.x = 100;
g.setYAxisTickSpacing(100);
g.setXAxisMax(5f);
}
void draw(){
background(200);
g.draw();
}
Not exactly sure if that code you have is what you need, but here is a simple program that takes in serial input and makes a line graph. Hope this helps.
import processing.serial.*;
Serial myPort;
int x = 0;
void setup() {
size(600, 400);
println(Serial.list()); //list of available serial ports
String portName = Serial.list()[0]; //replace 0 with whatever port you want to use.
myPort = new Serial(this, portName, 9600);
}
void draw() {
}
void serialEvent(Serial myPort) {
int inByte = myPort.read();
println(inByte);
stroke(90, 76, 99);
//vertical line with height varying according to input
line(x, height, x, height - inByte);
if (x >=width) {
x=0;
background(0);
}
x++;
}

Qt 4.7 - Drawing a 2 point line with dynamic feedback using paintEvent

so I am trying to draw a line between two points. Left mouse click starts the line then I would like the line to by dynamically drawn as the mouse moves (almost like a preview of the line). Left mouse click again and the line will be permanently drawn. I know there are a lot of other posts about QPaintEvents and I have combined some of the techniques used, but for some reason nothing is being drawn to the canvas. Below is the code:
void Main::mousePressEvent(QMouseEvent * event)
{
if (event->button() == Qt::LeftButton) {
QPointF pos = event->pos();
if( mStartPoint.isNull() ) {
if(josh.contains(pos))
mStartPoint = pos;
} else {
canvas.addLine(mStartPoint.x(),mStartPoint.y(),pos.x(),pos.y());
mStartPoint = QPointF();
}
}
}
bool Main::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseMove)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
if (!mStartPoint.isNull()) {
m_targetImage = QImage(canvas.width(),canvas.height(),QImage::Format_ARGB32);
QPainter p;
p.begin(&m_targetImage);
p.drawLine(mStartPoint, mouseEvent->pos());
p.end();
}
statusBar()->showMessage(QString("Mouse move (%1,%2)").arg(mouseEvent->pos().x()).arg(mouseEvent->pos().y()));
}
return false;
}
void Main::paintEvent(QPaintEvent *pe)
{
QPainter painter(this);
QPen pen(Qt::red);
pen.setWidth(10);
painter.setPen(pen);
painter.drawImage(0, 0, m_targetImage);
}
Any help is appreciated! Thanks! Josh
I think this is what you want. Change parameters according to your requirements.
//In your constructor
m_nInitialX = 0;
m_nInitialY = 0;
m_nFinalX = 0;
m_nFinalY = 0;
m_nPTargetPixmap = 0;
m_nPTargetPixmap = new QPixmap(400,400);
m_nbMousePressed = false;
void Main::mousePressEvent(QMouseEvent* event)
{
m_nbMousePressed = true;
m_nInitialX = event->pos().x();
m_nInitialY = event->pos().y();
}
void Main::mouseReleaseEvent(QMouseEvent *event)
{
m_nbMousePressed = false;
}
void Main::paintEvent(QPaintEvent *e)
{
if(m_nbMousePressed)
{
QPainter PixmapPainter(m_nPTargetPixmap);
QPen pen(Qt::green);
PixmapPainter.setPen(pen);
PixmapPainter.drawLine(m_nInitialX, m_nInitialY, m_nFinalX, m_nFinalY);
}
QPainter painter(this);
painter.drawPixmap(0, 0, *m_nPTargetPixmap);
}
void Main::mouseMoveEvent(QMouseEvent *event)
{
if (event->type() == QEvent::MouseMove)
{
QPainter PixmapPainter(m_nPTargetPixmap);
QPen pen(Qt::black);
PixmapPainter.setPen(pen);
PixmapPainter.drawLine(m_nInitialX, m_nInitialY, m_nFinalX, m_nFinalY);
update(); // update your view
m_nFinalX = event->pos().x();
m_nFinalY = event->pos().y();
}
update(); // update your view
}
This piece of code will draw a 2 point line that you want.
Here's my example of how to paint lines in your way directly on the widget.
Declaration:
private:
void drawLines(QPainter *p);
QPoint startPos;
QPoint endPos;
bool inDrawing;
QVector<QLine> lines;
Setting initial values in constructor:
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
startPos = QPoint();
endPos = QPoint();
inDrawing = false;
setMouseTracking(true);
}
Starting or ending the line drawing:
void Widget::mousePressEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
{
if (!inDrawing)
{
startPos = event->pos();
}
else
{
endPos = event->pos();
QLine line = QLine(startPos, event->pos());
lines.append(line);
}
inDrawing = !inDrawing;
}
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
if (inDrawing)
{
endPos = event->pos();
update();
}
}
Drawing current and saved lines:
void Widget::drawLines(QPainter *p)
{
if (!startPos.isNull() && !endPos.isNull())
{
p->drawLine(startPos, endPos);
}
p->drawLines(lines);
}
Drawing:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter p(this);
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(4);
p.setPen(pen);
drawLines(&p);
}

Resources