How to make sound play only once on mouse over in Processing? - audio

I'm trying to make a sound play when the mouse moves over a button in Processing. Currently, it is playing over and over again because my button class is in the draw() function. I understand why this is happening, but I can't think of a way to only play the sound once while still being tied to my overRect() function.
main:
import processing.sound.*;
PlayButton playButton;
SoundFile mouseOverSound;
SoundFile clickSound;
color white = color(255);
color gray = color(241, 241, 241);
PFont verdanabold;
void setup()
{
size(720, 1280);
textAlign(CENTER);
rectMode(CENTER);
verdanabold = createFont("Verdana Bold", 60, true);
playButton = new PlayButton();
mouseOverSound = new SoundFile(this, "mouseover.wav");
clickSound = new SoundFile(this, "click.mp3");
}
void draw()
{
background(gray);
playButton.display(); // draw play button
}
playButton class:
class PlayButton // play button
{
float rectX = width/2; // button x position
float rectY = height-height/4; // button y position
int rectWidth = 275; // button width
int rectHeight = 75; // button height
boolean rectOver = false; // boolean determining if mouse is over button
void display() // draws play button and controls its function
{
update(mouseX, mouseY);
if(rectOver) // controls button color when mouse over
{
fill(white);
mouseOverSound.play(); // play mouse over sound
}
else
{
fill(gray);
}
strokeWeight(5); // button
stroke(black);
rect(rectX, rectY, rectWidth, rectHeight);
textFont(verdanabold, 48); // button text
fill(black);
text("PLAY", rectX, rectY+15);
if(mousePressed && rectOver) // if mouse over and clicked, change to state 1
{
state = 1;
clickSound.play(); // play click sound
}
}
void update(float x, float y) // determines if mouse is over button using overRect(), changes boolean rectOver accordingly
{
if(overRect(rectX, rectY, rectWidth, rectHeight))
{
rectOver = true;
}
else
{
rectOver = false;
}
}
boolean overRect(float rectX, float rectY, int rectWidth, int rectHeight) // compares mouse pos to button pos and returns true if =
{
if(mouseX >= rectX-rectWidth/2 && mouseX <= rectX+rectWidth/2 && mouseY >= rectY-rectHeight/2 && mouseY <= rectY+rectHeight/2)
{
return true;
}
else
{
return false;
}
}
}

Figured it out.
Initialized int i = 0. While mouse is over the button, plays sound while i < 1, then increments i by 1 inside the while loop so it stops playing. When mouse is not over the button, i is set back to 0.
Edited playButton class:
class HowToButton // how to button
{
float rectX = width/2; // button x position
float rectY = height-height/8; // button y position
int rectWidth = 275; // button width
int rectHeight = 75; // button height
boolean rectOver = false; // boolean determining if mouse is over button
int i = 0;
void display() // draws how to button and controls its function
{
update(mouseX, mouseY);
if (rectOver) // controls button color when mouse over
{
fill(white);
while(i < 1) // play sound while i < 1
{
mouseOverSound.play(); // play mouse over sound
i++; // increment i so sound only plays once
}
}
else
{
fill(gray);
i = 0; // set i back to 0 when mouse leaves bounds of button
}
strokeWeight(5); // button
stroke(black);
rect(rectX, rectY, rectWidth, rectHeight);
textFont(verdanabold, 48); // button text
fill(black);
text("HOW TO", rectX, rectY+15);
if(mousePressed && rectOver) // if mouse over and clicked, change to state 2
{
state = 2;
clickSound.play(); // play click sound
}
}
void update(float x, float y) // determines if mouse is over button using overRect(), changes boolean rectOver accordingly
{
if(overRect(rectX, rectY, rectWidth, rectHeight))
{
rectOver = true;
}
else
{
rectOver = false;
}
}
boolean overRect(float rectX, float rectY, int rectWidth, int rectHeight) // compares mouse pos to button pos and returns true if =
{
if(mouseX >= rectX-rectWidth/2 && mouseX <= rectX+rectWidth/2 && mouseY >= rectY-rectHeight/2 && mouseY <= rectY+rectHeight/2)
{
return true;
}
else
{
return false;
}
}
}

You could use a boolean variable that indicates whether the sound is already playing. Something like this:
if(mousePressed && rectOver && !alreadyPlaying)
{
alreadyPlaying = true;
state = 1;
clickSound.play(); // play click sound
}
In fact, you might be able to use the state variable:
if(mousePressed && rectOver && state != 1)
{
state = 1;
clickSound.play(); // play click sound
}
You could also look into the sound library you're using, it might have a function that tells you whether the sound is already playing, which you could use in the same way.

Related

How to draw a string to the screen character by character

I have the below code that creates a delay in-between drawing characters from a string, this works using println() however does not work when using the text() function. The code is supposed to wait an allotted time then print the next character, I'm really not sure what I'm doing wrong.
int startTimer;
int waitTime = 500;
boolean funcRun = true;
void setup(){
size(500, 500);
startTimer = millis();
}
void draw(){
while(funcRun){
textAnim("hello");
}
}
void textAnim(String textInput){
int counter = 0;
int x = 10;
while(counter < textInput.length()){
if(millis() - startTimer>waitTime){
text(textInput.charAt(counter), x , 100);
startTimer = millis();
++counter;
x = x + 10;
}
funcRun = false;
}
}
The displayed screen is updated at the end of the draw() function. So your while loop is fully executed and the completed text is shown. You'll have to modify the code such that it will constantly refresh/redraw the screen, and updates the displayed text based on the time loop.
For example like this:
int currentTime;
int waitTime = 500;
int characters_to_display = 0;
boolean stringComplete = false;
String textInput = "Hello";
void setup() {
size(500, 500);
currentTime = millis();
}
void draw() {
// Update text to be shown. increaseCharIndex() is called while the text is not yet fully displayed
if (stringComplete == false) {
increaseCharIndex();
}
//Draw screen:
// draw background to clear screen
background(0);
// display (a substring of) the text
text(textInput.substring(0, characters_to_display), 10, 100);
}
void increaseCharIndex() {
// if the waitperiod has passed, increase the number of characters to be displayed
if (millis() - currentTime>waitTime) {
currentTime = millis();
characters_to_display++;
}
// if the full text will be shown, end the call to increaseCharIndex()
if (characters_to_display >= textInput.length())
{
stringComplete = true;
}
}

Switch Sound Button in Unity Javascript code

I am trying to figure out how to use "sound off" and "sound on" images to control game sound. The code below displays a sound button but when you click on it, it mutes the sounds but adds a shaded circle over the button.
I would like some guide or how to make it switch from a sound on to a sound off image button as I am new to Unity.
Image File Names: SoundButton.psd and WhiteCircle.psd
var whiteCircle : GameObject;
var numberOfTouch : int = 0;
private var a : float = 1;
function Start() {
if (PlayerPrefs.GetInt("SoundBoolean") == 0) {
//check whether the sound is included, if turned on, then play sound.
numberOfTouch = 0;
whiteCircle.GetComponent(SpriteRenderer).enabled = false;
}
if (PlayerPrefs.GetInt("SoundBoolean") == 1) {
//check whether the sound is included, if turned off, then turn off the sound.
numberOfTouch = 1;
whiteCircle.GetComponent(SpriteRenderer).enabled = true;
}
}
function OnMouseDown () {
if (a <= 0) {
if (numberOfTouch == 0) {
//completely turn off the music.
a = 1;
numberOfTouch = 1;
gameObject.GetComponent.<AudioSource>().Play();
whiteCircle.GetComponent(SpriteRenderer).enabled = true;
PlayerPrefs.SetInt("SoundBoolean", 1);
PlayerPrefs.Save();
}
}
if (a <= 0) {
if (numberOfTouch == 1) {
//a fully turn on the music.
a = 1;
numberOfTouch = 0;
whiteCircle.GetComponent(SpriteRenderer).enabled = false;
PlayerPrefs.SetInt("SoundBoolean", 0);
PlayerPrefs.Save();
}
}
}
function Update() {
if (a >= 0) {
a -= 0.1;
}
}
As I understood correctly, you're looking for something to change the sprite on an object you have. I'm not testing my code or anything, but perhaps it can help you solve your problem.
var sprite1 : Sprite; // Drag your first sprite here
var sprite2 : Sprite; // Drag your second sprite here
var spriteRenderer : SpriteRenderer = whiteCircle.GetComponent(SpriteRenderer);
var whiteCircle : GameObject;
var numberOfTouch : int = 0;
private var a : float = 1;
function Start() {
if (PlayerPrefs.GetInt("SoundBoolean") == 0) {
//check whether the sound is included, if turned on, then play sound.
numberOfTouch = 0;
spriteRenderer.sprite = sprite2;
}
if (PlayerPrefs.GetInt("SoundBoolean") == 1) {
//check whether the sound is included, if turned off, then turn off the sound.
numberOfTouch = 1;
spriteRenderer.sprite = sprite1;
}
}
function OnMouseDown () {
if (a <= 0) {
if (numberOfTouch == 0) {
//completely turn off the music.
a = 1;
numberOfTouch = 1;
gameObject.GetComponent.<AudioSource>().Play();
spriteRenderer.sprite = sprite1;
PlayerPrefs.SetInt("SoundBoolean", 1);
PlayerPrefs.Save();
}
}
if (a <= 0) {
if (numberOfTouch == 1) {
//a fully turn on the music.
a = 1;
numberOfTouch = 0;
spriteRenderer.sprite = sprite2;
PlayerPrefs.SetInt("SoundBoolean", 0);
PlayerPrefs.Save();
}
}
}
function Update() {
if (a >= 0) {
a -= 0.1;
}
}
Basically, add two sprite points to where you can drag your image files, then replace the sprite on a certain spriterenderer (instead of turning it on and off).

SDL multiple animations on same screen flicker

I am playing around with SDL, trying to make a simple fighting game like street fighter or such, but I don't understand how to make more than one animation at once on the screen without flickering. For some reason while both players are idle on the screen they don't flicker, but for other animations the second player flickers. The code looks something like this:
Class player1:
...
void setrects_idle(SDL_Rect* clip) //loads the frames from a bmp image
{
for(int i = 0; i < 10; i ++) {
clip[i].x = 0 + i*224;
clip[i].y = 0;
clip[i].w = 224;
clip[i].h = 226;
}
}
void setrects_walkf(SDL_Rect* clip)
{
for(int i = 0; i < 11; i ++) {
clip[i].x = 0 + i*224;
clip[i].y = 0;
clip[i].w = 224;
clip[i].h = 226;
}
}
void player::idle(SDL_Surface* screen)
{
if (!other_action)
{
SDL_BlitSurface(player1_idle, &frames_idle[static_cast<int>(frame_idle)], screen, &offset);
SDL_Flip(screen);
if(frame_idle > 8)
frame_idle = 0;
else
frame_idle ++;
}
}
void player::walkf(SDL_Surface* screen)
{
other_action = true;
SDL_BlitSurface(player1_walkf, &frames_walkf[static_cast<int>(frame_walkf)], screen, &offset);
SDL_Flip(screen);
if(frame_walkf > 9)
frame_walkf = 0;
else
frame_walkf ++;
}
********************
Class player2:
void player2::idle(SDL_Surface* screen)
{
if (!other_action)
{
SDL_BlitSurface(player2_idle, &frames_idle[static_cast<int>(frame_idle)], screen, &offset);
//SDL_Flip(screen); //with this commented, there is no flicker on both players idle
if(frame_idle > 8)
frame_idle = 0;
else
frame_idle ++;
}
}
void player2::walkf(SDL_Surface* screen)
{
other_action = true;
SDL_BlitSurface(player2_walkf, &frames_walkf[static_cast<int>(frame_walkf)], screen, &offset);
SDL_Flip(screen); //if I comment this there is no animation for player2 at all. with it on, it flickers.
if(frame_walkf > 9)
frame_walkf = 0;
else
frame_walkf ++;
}
*****************************
SDL_Surface *screen;
screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);
In the main loop:
player1.idle(screen);
player2.idle(screen);
...
case SDLK_d:
player1.b[1] = 1;
break;
case SDLK_j:
player2.b[1] = 1;
break;
...
if(player1.b[0])
player1.walkb(screen);
else
player1.return_to_idle();
if(player2.b[0])
player2.walkb(screen);
else
player2.return_to_idle();
You call several time SDL_Flip.
Into your main loop, call it juste once.
Erase background
Draw ALL objects.
Flip Once
Do not flip in your function walkf

How to play only one audio file at a time in minim

Here is what I have:
2 buttons
2 sounds
when button 1 press I want sound 1 played when button 2 pressed i want only sound2 played.
My code:
import ddf.minim.*;
RadioButtons r;
boolean showGUI = false;
Minim minim;
AudioPlayer player_1;
AudioPlayer player_2;
PImage img, img2;
PShape img1;
void setup() {
size(1024,735);
String[] radioNames = {"Button1", "Button2"};
r = new RadioButtons(radioNames.length, 20,700,50,30, HORIZONTAL);
r.setNames(radioNames);
img = loadImage("img.jpg");
img1 = loadImage("img1.png");
img2 = loadShape("img1.svg");
minim = new Minim(this);
//sound1
player_1 = minim.loadFile("sound1.wav");
//sound2
player_2 = minim.loadFile("soun2d2.wav");
}
void draw() {
//background(0);
//println (mouseX +"," + mouseY);
// Draw the image to the screen at coordinate (0,0)
//sound1
image(img,0,0);
if(r.get() == 0)
shape(img1,695,106);
if(mousePressed){
if(mouseX>695 && mouseX <695+190 && mouseY>106 && mouseY <106+180){
fill(0,0,0,0);
image(img2,300,150);
player_1.cue(0);
player_1.play();
}
}
//sound2
if(r.get() == 1)
shape(img1,695,106);
if(mousePressed){
if(mouseX>695 && mouseX <695+190 && mouseY>106 && mouseY <106+180){
fill(0,0,0,0);
image(img2,300,150);
player_2.cue(0);
player_2.play();
}
}
if(showGUI)
{
r.display();
}
}
void mouseReleased()
{
if(showGUI){
if(mouseY> height-60)
r.mouseReleased();
else
showGUI = false;
}
else{
showGUI = true;
}
}
At the moment both sounds play at the same time.
What am I missing?
You have to stop the current sample before you start the other one.
If you want to play player_2, you have to call:
player_1.pause();
player_1.rewind();
before you call player_2.play(); and the other way around.
UPDATE::
I Solved this by
Adding IF & ELSE IF statements.
EXAMPLE BELOW.
void draw() {
//background(0);
//println (mouseX +"," + mouseY);
// Draw the image to the screen at coordinate (0,0)
//sound1
image(img,0,0);
if(r.get() == 0)
{
code...
}
}
}
//sound2
else if(r.get() == 1)
{
code...
}
}
}
if(showGUI)
{
r.display();
}
}
I made this very stupid example, is it any help? It is stupid, specially the button class and event handling, but as I don't know which RadioButtons you are using I putted those lines together... maybe it can inspire you.
import ddf.minim.*;
PVector pOne, pTwo;
Button one, two;
Minim minim;
AudioPlayer player_1;
AudioPlayer player_2;
void setup() {
size(300,300);
pOne = new PVector(50, 150);
pTwo = new PVector(150, 150);
one = new Button (pOne, "one");
two = new Button (pTwo, "two");
minim = new Minim(this);
//sound1
player_2 = minim.loadFile("down_in_the_hole.mp3");
//sound2
player_1 = minim.loadFile("emotional_rescue.mp3");
}
void draw() {
background(220);
one.display();
one.update();
two.display();
two.update();
if(one.pressed){
player_2.pause();
player_1.rewind();
player_1.play();
ellipse(30,30,10,20);
// two.pressed = false;
}
if(two.pressed){
player_1.pause();
player_2.rewind();
player_2.play();
ellipse(130,30,10,20);
//one.pressed = false;
}
}
void mouseReleased(){
one.pressed = false;
two.pressed = false;
}
class Button{
String name;
PVector pos;
boolean pressed = false;
int xsz = 40;
int ysz = 20;
Button(PVector _pos, String _name ){
pos = _pos;
name = _name;
}
void display(){
color c = isOver()? 255:120;
fill(c);
rect(pos.x, pos.y, xsz, ysz);
fill(0);
text(name, pos.x+5, pos.y +ysz/2);
}
void update(){
if(isOver() && mousePressed)
pressed = true;
}
boolean isOver(){
return mouseX > pos.x && mouseX < pos.x + xsz &&
mouseY > pos.y && mouseY < pos.y + ysz;
}
}

Creating Tabmenu in j2me

Is there any way to create a Tab Menu in j2me?
I found a code but I am unable to understand it
In this code there is Tab Menu created which is in Canvas class and then Tab menu is created which is totally done in Canvas or painted. The only part I found difficult to grasp was the void go() method and then
When I try to draw anything above and below this code using paint method, it doesn't work - what's the problem?
Below is the code
// Tab Menu CANVAS class
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
public class TabMenuCanvas extends Canvas
{
TabMenu menu = null;
public TabMenuCanvas()
{
menu = new TabMenu(
new String[]{"Home", "News", "Community", "Your files", "Credits", "Events", "Blog", "Upload", "Forum Nokia"},
getWidth() - 20
);
}
protected void keyPressed(int key)
{
int gameAction = getGameAction(key);
if(gameAction == Canvas.RIGHT)
{
menu.goRight();
repaint();
}
else if(gameAction == Canvas.LEFT)
{
menu.goLeft();
repaint();
}
}
protected void paint(Graphics g)
{
g.translate(10, 30);
menu.paint(g);
g.translate(- 10, - 30);
}
}
// Tab Menu Class
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
public class TabMenu
{
int background = 0xffffff;
int bgColor = 0xcccccc;
int bgFocusedColor = 0x0000ff;
int foreColor = 0x000000;
int foreFocusedColor = 0xffffff;
int cornerRadius = 6;
int padding = 2;
int margin = 2;
Font font = Font.getDefaultFont();
int scrollStep = 20;
int selectedTab = 0; //selected tab index
int[] tabsWidth = null; //width of single tabs
int[] tabsLeft = null; //left X coordinate of single tabs
int tabHeight = 0; //height of tabs (equal for all tabs)
String[] tabs = null; //tab labels
int menuWidth = 0; //total menu width
int viewportWidth = 0; //visible viewport width
int viewportX = 0; //current viewport X coordinate
public TabMenu(String[] tabs, int width)
{
this.tabs = tabs;
this.viewportWidth = width;
initialize();
}
void initialize()
{
tabHeight = font.getHeight() + cornerRadius + 2 * padding; //[ same for all tabs]
menuWidth = 0;
tabsWidth = new int[tabs.length];
tabsLeft = new int[tabs.length];
for(int i = 0; i < tabsWidth.length; i++)
{
tabsWidth[i] = font.stringWidth(tabs[i]) + 2 * padding + 2 * cornerRadius;
tabsLeft[i] = menuWidth;
menuWidth += tabsWidth[i];
if(i > 0)
{
menuWidth += margin;
}
}
}
public void goRight()
{
go(+1);
}
public void goLeft()
{
go(-1);
}
private void go(int delta)
{
int newTab = Math.max(0, Math.min(tabs.length - 1, selectedTab + delta));
boolean scroll = true;
if(newTab != selectedTab && isTabVisible(newTab))
{
selectedTab = newTab;
if( (delta > 0 && tabsLeft[selectedTab] + tabsWidth[selectedTab] > viewportX + viewportWidth) ||
(delta < 0 && tabsLeft[selectedTab] < viewportX))
{
scroll = true;
}
else
{
scroll = false;
}
}
if(scroll)
{
viewportX = Math.max(0, Math.min(menuWidth - viewportWidth, viewportX + delta * scrollStep));
}
}
private boolean isTabVisible(int tabIndex)
{
return tabsLeft[tabIndex] < viewportX + viewportWidth &&
tabsLeft[tabIndex] + tabsWidth[tabIndex] >= viewportX;
}
public void paint(Graphics g)
{
int currentX = - viewportX;
g.setClip(0, 0, viewportWidth, tabHeight);
g.setColor(background);
g.fillRect(0, 0, viewportWidth, tabHeight);
for(int i = 0; i < tabs.length; i++)
{
g.setColor(i == selectedTab ? bgFocusedColor : bgColor);
g.fillRoundRect(currentX, 0, tabsWidth[i], tabHeight + cornerRadius, 2 * cornerRadius, 2 * cornerRadius);
g.setColor(i == selectedTab ? foreFocusedColor : foreColor);
g.drawString(tabs[i], currentX + cornerRadius + padding, cornerRadius + padding, Graphics.LEFT | Graphics.TOP);
currentX += tabsWidth[i] + margin;
}
}
}
When I try to draw anything above and below this code using paint method, it doesn't work
what of the paint methods you use to draw above and below? Pay attention that there are two methods named that way - first is in TabMenuCanvas, second is in TabMenu (second method is invoked from TabMenuCanvas#repaint).
whatever you would try to draw in TabMenuCanvas#paint will most likely be overwritten by setClip and fillRect when TabMenu#paint is invoked following repaint request
The only place where one can expect to be able to draw something visible seems to be in TabMenu#paint method, inside the clip area that is set there.
You can use GUI Libraries for J2ME,for example Lightweight User Interface Toolkit (LWUIT),Flemil have "tab menu".You can see list of GUI Libraries here.

Resources