Cocos2d CocosDenshion Sound Engine stop error - cocos2d-iphone

Thanks for taking the time to look as this question, I am very new to programming and am having a problem with the following error. Any help would be really appreciated.
I am currently learning via Ray Wenderlichs 'Learning Cocos2D' book but also experiment with the code to attempt to learn more and this is where I have run into a problem I can not fix.
I am using CocosDenshion to play the music tracks for the main menu and first gameplay scene, Ray advises in his book to call the following method from the GAMEPLAY SCENE...
[[GameManager sharedGameManager] playBackgroundTrack:BACKGOUND_TRACK_OLE_AWAKES];
This of course works but rather than call the above method in the gameplay scene I want to control the start and stopping of the music from my GameManager class.
So I want music to play in the menu and then nothing to play on the gameplay layer and to control it from one class.
To do this I have attempted to add the following in "GameManager.h.".
if (soundEngine.isBackgroundMusicPlaying == YES) {
[soundEngine stopBackgroundMusic];
}
In to the method below...
- (NSString*)formatSceneTypeToString:(SceneTypes)sceneID {
NSString *result = nil;
switch(sceneID) {
case kNoSceneUninitialized:
if ((soundEngine.isBackgroundMusicPlaying == YES)){
[soundEngine stopBackgroundMusic];
}
result = #"kNoSceneUninitialized";
break;
case kMainMenuScene:
if ((isSoundEffectsOn == YES)&&(soundEngine.isBackgroundMusicPlaying == NO)){
[self playBackgroundTrack:BACKGROUND_TRACK_MAIN_MENU];
} else if ((isSoundEffectsOn == NO)&&(soundEngine.isBackgroundMusicPlaying == YES)){
[soundEngine stopBackgroundMusic];
}
if (isMusicOn == YES) {
result = #"kMainMenuScene";
} else if (isMusicOn == NO) {
result = #"kNoSceneUninitialized";
// return NO;
}
break;
case kOptionsScene:
if ((isSoundEffectsOn == YES)&&(soundEngine.isBackgroundMusicPlaying == NO)){
[self playBackgroundTrack:BACKGROUND_TRACK_MAIN_MENU];
} else if ((isSoundEffectsOn == NO)&&(soundEngine.isBackgroundMusicPlaying == YES)){
[soundEngine stopBackgroundMusic];
}
if (isMusicOn == YES) {
result = #"kOptionsScene";
} else if (isMusicOn == NO) {
// return NO;
result = #"kNoSceneUninitialized";
}
break;
case kGameLevel1:
if ([soundEngine.isBackgroundMusicPlaying == YES]){
[soundEngine stopBackgroundMusic]; <--CRASHES HERE!
} else {
}
result = #"kGameLevel1";
break;
Now the above works fine for the MAIN MENU and OPTIONS screens when I run it but seems to crash when I attempt to load the GAMELEVEL1 screen. The crash only seems to occur once every now and then which is confusing to say the least.
When it crashes it takes me to the following in CDAudioManager.h..
-(BOOL) isPlaying {
if (state != kLAS_Init) {
return [audioSourcePlayer isPlaying]; <--Thread 18:EXC_BAD_ACCESS(code=1,address=0x8001400c)
} else {
return NO;
}
}
I also get the below in the console...
2014-10-28 12:46:03.948 SpaceViking[1807:343] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CCStandardTouchHandler isPlaying]: unrecognized selector sent to instance 0x7e013d80'
*** First throw call stack:
(
0 CoreFoundation 0x05bb25e4 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x025658b6 objc_exception_throw + 44
2 CoreFoundation 0x05c4f903 -[NSObject(NSObject) doesNotRecognizeSelector:] + 275
3 CoreFoundation 0x05ba290b ___forwarding___ + 1019
4 CoreFoundation 0x05ba24ee _CF_forwarding_prep_0 + 14
5 SpaceViking 0x00183e72 -[CDLongAudioSource isPlaying] + 82
6 SpaceViking 0x00185425 -[CDAudioManager isBackgroundMusicPlaying] + 69
7 SpaceViking 0x0018ea60 -[SimpleAudioEngine isBackgroundMusicPlaying] + 48
8 SpaceViking 0x0019fe62 -[GameManager formatSceneTypeToString:] + 9634
9 SpaceViking 0x001a095e -[GameManager getSoundEffectsListForSceneWithID:] + 2302
10 SpaceViking 0x0019d50a -[GameManager unloadAudioForSceneWithID:] + 186
11 Foundation 0x01e39597 -[NSThread main] + 76
12 Foundation 0x01e394f6 __NSThread__main__ + 1275
13 libsystem_pthread.dylib 0x02d185fb _pthread_body + 144
14 libsystem_pthread.dylib 0x02d18485 _pthread_struct_init + 0
15 libsystem_pthread.dylib 0x02d1dcf2 thread_start + 34
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
Sorry for the length of this question but wanted to try and include as much information as possible.
EDIT
I could be completely wrong but if the sound engine is called from 2 different classes would that cause this? As i have the following in the MainMenu layer...
-(void)playScene:(CCMenuItemFont*)itemPassedIn {
if ([itemPassedIn tag] == 1) {
CCLOG(#"Tag 1 found, mode");
if ([GameManager sharedGameManager].isSoundEffectsOn ==YES ) {
PLAYSOUNDEFFECT(BUTTONPRESS); <----Calling the sound engine to play a sound on button press.- this is unloading the sound as level1 starts.
[[GameManager sharedGameManager] runSceneWithID:kGameLevel1];
}else if ([GameManager sharedGameManager].isSoundEffectsOn ==NO ) {
[[GameManager sharedGameManager] runSceneWithID:kGameLevel1];
return;
}

Related

How do I have the serial monitor of the Arduino show a string a value but only the value is changing?

I already have my code to work, I'm just trying to make it look nicer now. Just to give a really short summary on what my device does: Smart parking system that detects cars going in and out of a parking lot and displays how many vacant spots are available or not at the entrance. Right now the output looks like this:
Vacant Spots: 1
Vacant Spots: 1
Vacant Spots: 1
Vacant Spots: 1
Vacant Spots: 0
.
.
.
.
.
This is in the case of when a car is entering so it's decrementing by 1 and it increments when a car leaves since there's a added vacant spot available. What I'm trying to do is have the output look like this:
"
Vacant Spots: 1
"
The only thing I want to change is the numerical value. I don't want a continuous stream of
" Vacant Spots: 1 "s to show at the LCD display for the parking user to see. Is there a way to just clear the serial monitor after the loop ends without having it output a new value below it continuously? I've provided the code for the program. I have 3 xbees (1 coordinator and 2 routers). The two routers dont have code on them and are just sending data to the coordinator. The coordinator is where it receives the data. This is the code for the coordinator:
int readValue = 0;
void setup()
{
Serial.begin(9600);
}
int vslots = 1;
void loop()
{
if(Serial.available()>21)
{
if(Serial.read() == 0x7E)
{
for(int i=0;i<19;i++)
{
byte discard = Serial.read(); //Next 18 bytes, it's discarded
}
readValue = Serial.read();
bool flagTrue = false;
bool flagFalse = false;
if((readValue == 0) && flagTrue == false ) //EXIT
{
flagTrue = true;
flagFalse = false;
Serial.print("Vacant Spots: ");
Serial.println(vslots);
}
else if((readValue == 16 && flagFalse == false) && vslots >= 1)
//DECREMENT (CAR ENTERING)
{
flagTrue = false;
flagFalse = true;
vslots -= 1;
Serial.print("Vacant Spots: ");
Serial.println(vslots);
}
if((readValue == 18) && flagTrue == false )
{
flagTrue = true;
flagFalse = false;
Serial.print("Vacant Spots: ");
Serial.println(vslots);
}
else if((readValue == 19 && flagFalse == false) && vslots <= 10)
//INCREMENT (CAR EXITING)
{
flagTrue = false;
flagFalse = true;
vslots += 1;
Serial.print("Vacant Spots: ");
Serial.println(vslots);
}
}
}
}
First, you need to understand that Arduino serial terminal is not like a real terminal software It does not support a command sent on UART. So to achieve what you want you will require real terminal software such as putty. Which allows you to make changes by sending character bytes using UART communication.
//ADD these lines before printing on a serial terminal
Serial.write(27); // 27 is an ESC command for terminal
Serial.print("[2J"); // this will clear screen
Serial.write(27); // 27 is an ESC command for terminal
Serial.print("[H"); // move cursor to home
//now print what you want...
Serial.print("Vacant Spots: ");
Serial.println(vslots);
For more info and methods you can check this post here. But had tried everything and suggesting to go with putty.
The ln suffix in println stands for new line. That means println will "print" the value and a newline.
So as an initial solution you could change from using println to plain print:
Serial.print("Vacant Spots: ");
Serial.print(vslots); // Note: not println
Then we have to solve the problem of going back to the beginning of the line. to overwrite the old text. This is typically done with the carriate-return character '\r'. If we add it to the beginning of the printout:
Serial.print("\rVacant Spots: "); // Note initial cariage-return
Serial.print(vslots); // Note: not println
Then each printout should go back to the beginning of the line, and overwrite the previous content on that line.
To make sure that each line is equally long, you could use e.g. sprintf to format the string first, and then write it to the serial port:
char buffer[32];
// - for left justification,
// 5 for width of value (padded with spaces)
sprintf(buffer, "\rVacant Spots: %-5d", vslots);
Serial.print(buffer);

C++ nested If statement, it doesn't work as expected

StackOverflow fellow developers,
I am doing some Arduino coding to working with measuring Fine Dust Monitoring Device,
However, I have a question regarding with If-statement.
In the code below, I added nested-if statement in the while loop, and some reason,
else if (9999 >= int(pm25s.getMedian()) && int(pm25s.getMedian()) >= 52) {
pm25i = 7;
}
else if (9999 >= int(pm10s.getMedian()) && int(pm10s.getMedian()) >= 102) {
pm10i = 7;
}
else if (pm10i == 7) {
status = "Hazardous (7) : Health warnings of emergency conditions. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are strongly discouraged.";
}
}
Those lines doesn't work as expected, as when pm10 or pm25 value reaches more than 100 ug / m^3, it doesn't sync with the ThingSpeak server anymore, but I don't know why it doesn't uploads any data. Interestingly rest of my source code parts work fine as expected.
However When I removed those nested-if statements it works fine. (It successfully uploads even pm10 or pm25 value reaches more than 100 ug / m^3.
Could somebody explain what's wrong with my code? and how should I fix this issue please?
Thanks.
void loop() {
if (ss.available() <= 0) {
Serial.println("SIGNAL STATUS : WEAK");
s_map_x = String(map_x, 6);
s_map_y = String(map_y, 6);
}
else {
while (ss.available() > 0) {
Serial.println("SIGNAL STATUS : GREAT");
if (gps.encode(ss.read())) {
Serial.println("GPS READ");
Serial.println(ss.read());
if (gps.location.isValid()) {
Serial.println("LOCATION : GREAT");
map_x = gps.location.lat();
map_y = gps.location.lng();
Serial.println(String(map_x, 6));
Serial.println(String(map_y, 6));
Serial.println(gps.satellites.value());
}
}
s_map_x = String(map_x, 6);
s_map_y = String(map_y, 6);
yield();
}
}
while (dust.available() > 0) {
do_dust(dust.read(), got_dust);
yield();
/* AQI (실시간 대기질 지수) 등급 분류를 위한 코드입니다.
실시간 대기질 기준 수치는 국제 표준인 WHO 대기질 수치 기준으로 분류합니다.
http://www.euro.who.int/__data/assets/pdf_file/0005/78638/E90038.pdf
https://airnow.gov/index.cfm?action=aqibasics.aqi */
// 초미세먼지 AQI (실시간 대기질 지수) 등급을 분류합니다.
// 0 이상 8 이하 : 1
// 9 이상 16 이하 : 2
// 17 이상 26 이하 : 3
// 27 이상 34 이하 : 4
// 35 이상 43 이하 : 5
// 44 이상 51 이하 : 6
// 52 이상 ∞ 이하 : 7
if (8 >= int(pm25s.getMedian()) && int(pm25s.getMedian()) >= 0) {
pm25i = 1;
}
else if (16 >= int(pm25s.getMedian()) && int(pm25s.getMedian()) >= 9) {
pm25i = 2;
}
else if (26 >= int(pm25s.getMedian()) && int(pm25s.getMedian()) >= 17) {
pm25i = 3;
}
else if (34 >= int(pm25s.getMedian()) && int(pm25s.getMedian()) >= 27) {
pm25i = 4;
}
else if (43 >= int(pm25s.getMedian()) && int(pm25s.getMedian()) >= 35) {
pm25i = 5;
}
else if (51 >= int(pm25s.getMedian()) && int(pm25s.getMedian()) >= 44) {
pm25i = 6;
}
else if (9999 >= int(pm25s.getMedian()) && int(pm25s.getMedian()) >= 52) {
pm25i = 7;
}
// 미세먼지 AQI (실시간 대기질 지수) 등급을 분류합니다.
// 0 이상 8 이하 : 1
// 9 이상 16 이하 : 2
// 17 이상 51 이하 : 3
// 52 이상 68 이하 : 4
// 69 이상 84 이하 : 5
// 85 이상 101 이하 : 6
// 102 이상 ∞ 이하 : 7
if (8 >= int(pm10s.getMedian()) && int(pm10s.getMedian()) >= 0) {
pm10i = 1;
}
else if (16 >= int(pm10s.getMedian()) && int(pm10s.getMedian()) >= 9) {
pm10i = 2;
}
else if (51 >= int(pm10s.getMedian()) && int(pm10s.getMedian()) >= 17) {
pm10i = 3;
}
else if (68 >= int(pm10s.getMedian()) && int(pm10s.getMedian()) >= 52) {
pm10i = 4;
}
else if (84 >= int(pm10s.getMedian()) && int(pm10s.getMedian()) >= 69) {
pm10i = 5;
}
else if (101 >= int(pm10s.getMedian()) && int(pm10s.getMedian()) >= 85) {
pm10i = 6;
}
else if (9999 >= int(pm10s.getMedian()) && int(pm10s.getMedian()) >= 102) {
pm10i = 7;
}
/* ThingSpeak 채널 내 Status Update (상태 업데이트) 영역에 표시되는 문구이므로,
종합적인 정보 표현을 위해 초미세먼지와 미세먼지 등급을 비교 한 후
두 가지 중 높은 등급 기준으로 경고 혹은 권고메시지를 표시합니다. */
// 분류된 초미세먼지 등급이 미세먼지 등급보다 같거나 높은 경우, 초미세먼지 등급을 기준으로 내용을 표시하기 위하여 아래의 문자열을 status 변수에 저장합니다.
if (pm25i >= pm10i) {
if (pm25i == 1) {
status = "Excellent (1) : The air quality is excellent. The air pollution pose no threat. The conditions ideal for outdoor activities.";
}
else if (pm25i == 2) {
status = "Very Good (2) : Air quality is very good, and air pollution poses little or no risk. Conditions very good for outdoor activities.";
}
else if (pm25i == 3) {
status = "Moderate (3) : Air quality is acceptable. however, for some pollutants there may be a moderate health concern for a very small number of people who are unusually sensitive to air pollution.";
}
else if (pm25i == 4) {
status = "Satisfactory (4) : Members of sensitive groups may experience health effects, Other people should limit spending time outdoors, especially when they experience symptoms such as cough or sore throat.";
}
else if (pm25i == 5) {
status = "Bad (5) : Everyone may begin to experience health effects, members of sensitive groups may experience more serious health effects. People at risk should avoid to go outside. Not recommended for outdoor activities.";
}
else if (pm25i == 6) {
status = "Severe (6) : Air quality is severe. Everyone may experience more serious health effects. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are discouraged.";
}
else if (pm25i == 7) {
status = "Hazardous (7) : Health warnings of emergency conditions. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are strongly discouraged.";
}
// 분류된 미세먼지 등급이 초미세먼지 등급보다 높은 경우, 미세먼지 등급을 기준으로 내용을 표시하기 위하여 아래의 문자열을 status 변수에 저장합니다.
} else if (pm25i < pm10i) {
if (pm10i == 1) {
status = "Excellent (1) : The air quality is excellent. The air pollution pose no threat. The conditions ideal for outdoor activities.";
}
else if (pm10i == 2) {
status = "Very Good (2) : Air quality is very good, and air pollution poses little or no risk. Conditions very good for outdoor activities";
}
else if (pm10i == 3) {
status = "Moderate (3) : Air quality is acceptable. however, for some pollutants there may be a moderate health concern for a very small number of people who are unusually sensitive to air pollution.";
}
else if (pm10i == 4) {
status = "Satisfactory (4) : Members of sensitive groups may experience health effects, Other people should limit spending time outdoors, especially when they experience symptoms such as cough or sore throat.";
}
else if (pm10i == 5) {
status = "Bad (5) : Everyone may begin to experience health effects, members of sensitive groups may experience more serious health effects. People at risk should avoid to go outside. Not recommended for outdoor activities.";
}
else if (pm10i == 6) {
status = "Severe (6) : Air quality is severe. Everyone may experience more serious health effects. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are discouraged.";
}
else if (pm10i == 7) {
status = "Hazardous (7) : Health warnings of emergency conditions. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are strongly discouraged.";
}
}
}
//Serial.println(map_x);
//Serial.print("pm 25 : ");
//Serial.println(int(pm25s.getMedian()));
if (millis() > mark) {//one minute(60000) interval
mark = millis() + 60000;
got_interval = true;
}
if (got_interval) {
got_interval = false;
do_interval();
}
yield();
}
You may be getting unexpected behavior due to floating point comparisons or may be due to some unhandled cases, or may be because RunningMedian::getMedian() is changing on any/every condition check. Another possible reason is maybe RunningMedia::_cnt is not more than 0.
Also I would recommend updating your library to its latest version (v0.1.15).
Try putting this code inside your while loop:
float _pm25Median = pm25s.getMedian();
float _pm10Median = pm10s.getMedian();
if (isnan(_pm25Median) || isnan(_pm10Median))
continue; // or do something else to handle this exception properly
if (_pm25Median < 9)
pm25i = 1;
else if (_pm25Median < 17)
pm25i = 2;
else if (_pm25Median < 27)
pm25i = 3;
else if (_pm25Median < 35)
pm25i = 4;
else if (_pm25Median < 44)
pm25i = 5;
else if (_pm25Median < 52)
pm25i = 6;
else
pm25i = 7;
if (_pm10Median < 9)
pm10i = 1;
else if (_pm10Median < 17)
pm10i = 2;
else if (_pm10Median < 52)
pm10i = 3;
else if (_pm10Median < 69)
pm10i = 4;
else if (_pm10Median < 85)
pm10i = 5;
else if (_pm10Median < 102)
pm10i = 6;
else
pm10i = 7;
if (pm25i >= pm10i) {
switch (pm25i) {
case 1:
status = "Excellent (1) : The air quality is excellent. The air pollution pose no threat. The conditions ideal for outdoor activities.";
break;
case 2:
status = "Very Good (2) : Air quality is very good, and air pollution poses little or no risk. Conditions very good for outdoor activities.";
break;
case 3:
status = "Moderate (3) : Air quality is acceptable. however, for some pollutants there may be a moderate health concern for a very small number of people who are unusually sensitive to air pollution.";
break;
case 4:
status = "Satisfactory (4) : Members of sensitive groups may experience health effects, Other people should limit spending time outdoors, especially when they experience symptoms such as cough or sore throat.";
break;
case 5:
status = "Bad (5) : Everyone may begin to experience health effects, members of sensitive groups may experience more serious health effects. People at risk should avoid to go outside. Not recommended for outdoor activities.";
break;
case 6:
status = "Severe (6) : Air quality is severe. Everyone may experience more serious health effects. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are discouraged.";
break;
case 7:
status = "Hazardous (7) : Health warnings of emergency conditions. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are strongly discouraged.";
default:
break;
}
} else {
switch (pm10i) {
case 1:
status = "Excellent (1) : The air quality is excellent. The air pollution pose no threat. The conditions ideal for outdoor activities.";
break;
case 2:
status = "Very Good (2) : Air quality is very good, and air pollution poses little or no risk. Conditions very good for outdoor activities";
break;
case 3:
status = "Moderate (3) : Air quality is acceptable. however, for some pollutants there may be a moderate health concern for a very small number of people who are unusually sensitive to air pollution.";
break;
case 4:
status = "Satisfactory (4) : Members of sensitive groups may experience health effects, Other people should limit spending time outdoors, especially when they experience symptoms such as cough or sore throat.";
break;
case 5:
status = "Bad (5) : Everyone may begin to experience health effects, members of sensitive groups may experience more serious health effects. People at risk should avoid to go outside. Not recommended for outdoor activities.";
break;
case 6:
status = "Severe (6) : Air quality is severe. Everyone may experience more serious health effects. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are discouraged.";
break;
case 7:
status = "Hazardous (7) : Health warnings of emergency conditions. People at risk should be avoided to go outside and should limit the outdoor activities to minimum. Outdoor activities are strongly discouraged.";
break;
default:
break;
}
}

Bukkit countdown message sends message 4 times

I just created a countdown method in Java, but i have a problem when the countdowner broadcasts the messages: 60(and down) seconds until the game starts!
The broadcast gets sent *4. Does anyone know any solution to this?
Here is my code:
Main plugin;
public StartCountdown(Main pl) {
plugin = pl;
}
public static int timeUntilStart;
#Override
public void run() {
for(Player p1 : Bukkit.getOnlinePlayers()){
if(timeUntilStart == 0) {
if(!Game.canStart()) {
plugin.restartCountdown();
ChatUtilities.broadcast(ChatColor.RED + "Not enough players to start. Countdown will");
ChatUtilities.broadcast(ChatColor.RED + "restart.");
p1.playSound(p1.getLocation(), Sound.ENDERDRAGON_WINGS, 5, 1);
return;
}
Game.start();
}
for(Player p : Bukkit.getOnlinePlayers()){
p.setLevel(timeUntilStart);
if(timeUntilStart < 11 || timeUntilStart == 60 || timeUntilStart == 30) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 0);
if(timeUntilStart == 1) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 1);
}
ChatUtilities.broadcast(String.valueOf(timeUntilStart)
+ " §6Seconds until the game starts!");
}
}
}
timeUntilStart -= 1;
}
}
You are broadcasting for every player that is online. You need to move any code that you don't want to run for every player outside of the for loop.
#Override
public void run() {
if (timeUntilStart == 0) {
if (!Game.canStart()) {
plugin.restartCountdown();
ChatUtilities.broadcast(ChatColor.RED + "Not enough players to start. Countdown will");
ChatUtilities.broadcast(ChatColor.RED + "restart.");
for (Player p : Bukkit.getOnlinePlayers()) p.playSound(p.getLocation(), Sound.ENDERDRAGON_WINGS, 5, 1);
return;
}
Game.start();
}
boolean broadcast;
for (Player p : Bukkit.getOnlinePlayers()) {
p.setLevel(timeUntilStart);
if (timeUntilStart < 11 || timeUntilStart == 60 || timeUntilStart == 30) {
p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 0);
if (timeUntilStart == 1) p.playSound(p.getLocation(), Sound.ORB_PICKUP, 5, 1);
broadcast = true;
}
}
if (broadcast) ChatUtilities.broadcast(String.valueOf(timeUntilStart) + " §6Seconds until the game starts!");
timeUntilStart -= 1;
}
as Tanner Little said above
You are broadcasting for every player that is online. You need to move any code that you don't want to run for every player outside of the for loop.
You need to make sure as well that you are cancelling the task. I would recommend using the inbuilt scheduler. You can access the scheduler in this way
private int countDownTimer
private int countDownTime
public void runCountDown() {
countDownTimer = Bukkit.getScheduler.scheduleSyncDelayedTask(plugin, new runnable() {
public void run {
if (countDownTime <= 0) {
//do your bradcasting here
for (Player ingame : Bukkit.getOnlinePlayers()) {
//Do your player specific stuff here
}
Bukkit.getScheduler.cancelTask(countDownTimer);
}
if (countDownTime % 10 == 0) { //You can pick whaterver times u want this is just for an example
//Do periodic broadcasting
}
countDownTime -= 1;
}
}, 0L, 20L); //This means that it would wait 0 ticks to start the countdown and do the task every 20 ticks ie) 1 second.
}
Hopefully this helps you.

Can't find cause of crash

I'm trying to add the RedLaser SDK to my project, and when trying to open the PickerController I get an error at:
0x39b70538: push {r4, r5, r6, r7, lr}.
This is the code how I instantiate the PickerController:
- (IBAction) redBoxScanButtonPressed
{
RLSampleViewControllerRequestVideoAuthorization(^void (void) {
RedBoxPickerController *redBoxPickerController =
[[RedBoxPickerController alloc] initWithNibName:#"RedBoxPickerController" bundle:nil];
redBoxPickerController.delegate = self;
// hide the status bar and show the scanner view
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self presentViewController:redBoxPickerController animated:NO completion:nil];// presentModalViewController:redBoxPickerController animated:FALSE];
//[redBoxPickerController release];
});
}
method to request Authorization:
static void RLSampleViewControllerRequestVideoAuthorization(dispatch_block_t completionHandler) {
RL_RequestVideoAuthorization(^void (RL_VideoAuthorizationStatus status) {
if (status == RL_VideoAuthorizationStatusAuthorized) {
dispatch_async(dispatch_get_main_queue(), ^void (void) {
completionHandler();
});
}
});
}
BackTrace
(lldb) bt
* thread #11: tid = 0xc81db, 0x39b70538 libc++abi.dylib`__cxa_throw, queue = 'ZXing', stop reason = breakpoint 1.2 * frame #0: 0x39b70538 libc++abi.dylib`__cxa_throw
frame #1: 0x00187e32 IRON TRAINERS`zxing::GlobalHistogramBinarizer::estimate(std::vector<int, std::allocator<int> >&) + 370
frame #2: 0x00187f60 IRON TRAINERS`zxing::GlobalHistogramBinarizer::getBlackMatrix() + 268
frame #3: 0x00186580 IRON TRAINERS`zxing::BinaryBitmap::getBlackMatrix() + 12
frame #4: 0x001a9b00 IRON TRAINERS`zxing::qrcode::QRCodeReader::decode(zxing::Ref<zxing::BinaryBitmap>, zxing::DecodeHints) + 44
frame #5: 0x001b086e IRON TRAINERS`zxing::Reader::decode(zxing::Ref<zxing::BinaryBitmap>) + 278
frame #6: 0x001b4a86 IRON TRAINERS`-[FormatReader decode:] + 142
frame #7: 0x00185da8 IRON TRAINERS`-[ZXingDecoder findCodesInBitmap:bytesPerRow:width:height:] + 796
frame #8: 0x001ba93e IRON TRAINERS`-[BarcodePhotoEngine zxingFindBarcodesInPixmap:] + 226
frame #9: 0x001b318c IRON TRAINERS`__38-[BarcodeEngine findBarcodesInPixMap:]_block_invoke55 + 76
frame #10: 0x0081e172 libdispatch.dylib`_dispatch_call_block_and_release + 10
frame #11: 0x00826d66 libdispatch.dylib`_dispatch_queue_drain + 1718
frame #12: 0x00820a60 libdispatch.dylib`_dispatch_queue_invoke + 88
frame #13: 0x00828b08 libdispatch.dylib`_dispatch_root_queue_drain + 1308
frame #14: 0x00829e18 libdispatch.dylib`_dispatch_worker_thread3 + 100
frame #15: 0x3a91adc0 libsystem_pthread.dylib`_pthread_wqthread + 668 (lldb)
I'm not sure what to look for, I've tried to add a few breakpoints but didn't find the problem.
The sample project works fine, so I guess I'm missing some code.
Here is the complete code of the PickerController:
/*******************************************************************************
RedBoxPickerController.m
Part of RLSample
This is a scan overlay example that frames discovered barcodes with red boxes.
Chall Fry
November 2012
Copyright (c) 2012 eBay Inc. All rights reserved.
*/
#import "RedBoxPickerController.h"
#implementation RedBoxPickerController
/*******************************************************************************
didReceiveMemoryWarning
*/
- (void) didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
/*******************************************************************************
viewWillAppear:
Sets up the initial state of UI elements in the overlay.
*/
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
inRangeLabel.hidden = true;
numBarcodesFoundLabel.text = #"";
torchButton.enabled = self.hasTorch;
torchButton.style = self.isTorchOn ? UIBarButtonItemStyleDone :
UIBarButtonItemStyleBordered;
}
#pragma mark Button Handlers
/*******************************************************************************
cancelScan
Action proc for the 'Done' button.
*/
- (IBAction) cancelScan
{
[self doneScanning];
}
/*******************************************************************************
captureImage
Action proc for the 'Cap' button.
Need to have reportCameraImage enabled for this.
*/
- (IBAction) captureImage
{
if (!imageSaveInProgress)
{
[self requestCameraSnapshot:true];
savingImageLabel.hidden = false;
captureButton.enabled = false;
}
}
/*******************************************************************************
toggleFrontBackCamera
Action proc for the 'Front/Back' button.
*/
- (IBAction) toggleFrontBackCamera
{
self.useFrontCamera = !self.useFrontCamera;
}
/*******************************************************************************
toggleTorch
Action proc for the 'Light' button.
*/
- (IBAction) toggleTorch
{
[self turnTorch:!self.isTorchOn];
torchButton.style = self.isTorchOn ? UIBarButtonItemStyleDone :
UIBarButtonItemStyleBordered;
}
#pragma mark Status Updates
/*******************************************************************************
statusUpdated:
The RedLaser SDK will call this method repeatedly while scanning for barcodes.
*/
- (void) statusUpdated:(NSDictionary*) status
{
NSSet *foundBarcodes = [status objectForKey:#"FoundBarcodes"];
// Report how many barcodes we've found so far
numBarcodesFoundLabel.text = [NSString stringWithFormat:#"%d Barcodes found",
[foundBarcodes count]];
// Show the right guidance string for the guidance level
// Guidance is used for detecting long Code 39 codes in parts.
// See the documentation for more info.
int guidanceLevel = [[status objectForKey:#"Guidance"] intValue];
if (guidanceLevel == 1)
{
guidanceLabel.text = #"Try moving the camera close to each part of the barcode";
} else if (guidanceLevel == 2)
{
guidanceLabel.text = [NSString stringWithFormat:#"%#…",
[status objectForKey:#"PartialBarcode"]];
} else {
guidanceLabel.text = #"";
}
// Show the in range label if we're in range of an EAN barcode
inRangeLabel.hidden = ![[status objectForKey:#"InRange"] boolValue];
// Tell the Red Box View to update its display
redBoxView.barcodes = foundBarcodes;
[redBoxView setNeedsDisplay];
// If the user clicked the "Capture" button, this key will have a UIImage in it
// on a subsequent statusUpdated call. Otherwise, the key won't be present.
// If we have a camera image, save it to the device's photo album.
UIImage *cameraImage = [status objectForKey:#"CameraSnapshot"];
if (cameraImage && cameraImage != (id) [NSNull null])
{
imageSaveInProgress = true;
UIImageWriteToSavedPhotosAlbum(cameraImage, self,
#selector(image:didFinishSavingWithError:contextInfo:), nil);
}
}
/*******************************************************************************
image:didFinishSavingWithError:contextInfo:
Called when UIImageWriteToSavedPhotosAlbum() has finished saving an image to
the camera roll.
Reenables the Capture button and hides the "Saving Image..." label.
*/
- (void) image: (UIImage *) image didFinishSavingWithError: (NSError *) error
contextInfo: (void *) contextInfo
{
imageSaveInProgress = false;
savingImageLabel.hidden = true;
captureButton.enabled = true;
}
#end
#implementation RedBoxView
#synthesize barcodes;
/*******************************************************************************
drawRect:
RedBoxView is a UIView subclass that exists to override this method.
When it redraws itself, it looks for any barcodes in the found barcode set that
have been 'seen' in the last second, makes a UIBezierPath from the corner
locations of the barcode, and then fills and strokes the path.
*/
- (void) drawRect:(CGRect)rect
{
for (BarcodeResult *val in self.barcodes)
{
// Has this barcode been seen on-screen recently, or is it stale?
if ([val.mostRecentScanTime timeIntervalSinceNow] < -1.0)
{
continue;
}
// Don't bother displaying a path that only has 2 points--this is rare but can happen
if ([val.barcodeLocation count] < 2)
continue;
// Generate a UIBezierPath of the points, close it, and fill it
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:[[val.barcodeLocation objectAtIndex:0] CGPointValue]];
for (int index = 1; index < [val.barcodeLocation count]; ++index)
{
[path addLineToPoint:[[val.barcodeLocation objectAtIndex:index] CGPointValue]];
}
[path closePath];
[[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.2] set];
[path fill];
[[UIColor colorWithRed:1.0 green:0.0 blue:0.0 alpha:0.3] set];
[path stroke];
}
// Be sure to clear out the barcodes once we've drawn them
self.barcodes = nil;
}
- (void) didMoveToSuperview
{
CGRect superviewFrame = [[self superview] frame];
superviewFrame.origin.x = superviewFrame.origin.y = 0;
self.frame = superviewFrame;
[super didMoveToSuperview];
}
#end
You can "Enable Zombie Objects" in you application scheme. This will give you proper error messages.
Just Click on you application name ( Right side of stop button on xCode ) then click on Edit Scheme then click on RUN in left Panel now go to "Diagnostics" tab there you will see Memory Management header under which you can enable "Enable Zombie Objects".
Hope this will help you.

How to add CCLabelBMFont to the NSMutableArray

I am creating my first game with cocos2D. And I have a problem looking for help.
I want to create some selected numbers and falling down randomly.
so this is what I did for the programe.
In my HelloWorldLayer.m
-(id) init
{
if( (self=[super init]) ) {
screenSize = [CCDirector sharedDirector].winSize;
CCSprite* background = [CCSprite spriteWithFile:#"game.png"];
background.position = ccp(screenSize.width/2, screenSize.height/2);
[self addChild:background z:0];
operatorArray = [[NSMutableArray alloc] init];
fallingNumberArray = [[NSMutableArray alloc] init];
[[[CCDirector sharedDirector] scheduler] scheduleSelector:#selector(update:) forTarget:self interval:0.0 paused:NO];
// Falling Number Font Type & Position
fallingNumber = [CCLabelBMFont labelWithString:#"99" fntFile:#"MyHelveticaCondensed.fnt"];
fallingNumber.anchorPoint=ccp(0.5f,0.5f);
fallingNumber.position = ccp(160,180);
[self addChild:fallingNumber z:3];
}
return self;
}
I have a method to generate the color for the numbers
-(void) colorFallingNumber{
// FallingNumber random and color ------------- START CODE -------------
do {
fallNum = (arc4random() % 60) + 1;
}
while ( fallNum == 23 || fallNum == 29 || fallNum == 31 || fallNum == 35 || fallNum == 37 || fallNum == 41 || fallNum == 43|| fallNum == 44|| fallNum == 46|| fallNum == 47|| fallNum == 49 || fallNum == 52|| fallNum == 53 || fallNum == 55 || fallNum == 56 || fallNum == 58|| fallNum == 59);
if (fallNum == 1 ||fallNum == 7 ||fallNum == 13 ||fallNum == 19 ||fallNum == 26 ||fallNum == 34 ||fallNum == 45 ||fallNum == 60) {
fallingNumber.color = ccc3(217,101,75);
}
if (fallNum == 2 ||fallNum == 8 ||fallNum == 14 ||fallNum == 20 ||fallNum == 27 ||fallNum == 36 ||fallNum == 48) {
fallingNumber.color = ccc3(79,166,134);
}
if (fallNum == 3 ||fallNum == 9 ||fallNum == 14 ||fallNum == 21 ||fallNum == 28 ||fallNum == 38 ||fallNum == 50) {
fallingNumber.color = ccc3(217,148,15);
}
if (fallNum == 4 ||fallNum == 10 ||fallNum == 16 ||fallNum == 22 ||fallNum == 30 ||fallNum == 39 ||fallNum == 51) {
fallingNumber.color = ccc3(209,75,217);
}
if (fallNum == 5 ||fallNum == 11 ||fallNum == 17 ||fallNum == 24 ||fallNum == 32 ||fallNum == 40 ||fallNum == 54) {
fallingNumber.color = ccc3(75,149,217);
}
if (fallNum == 6 ||fallNum == 12 ||fallNum == 18 ||fallNum == 25 ||fallNum == 33 ||fallNum == 42 ||fallNum == 57) {
fallingNumber.color = ccc3(217,75,32);
}
}
And this is update method
-(void) update:(ccTime)dt{
NSMutableArray* removeArray = [NSMutableArray array];
[self colorFallingNumber];
fallingNumber.string = [NSString stringWithFormat:#"%d",fallNum];
NSString *fallingNumberName = [NSString stringWithFormat:#"%d",fallNum]; ////// I think here is the problem
FallingNumber *newFallingNumber = [[NSClassFromString(fallingNumberName) alloc] init]; ////// I think here is the problem
[newFallingNumber animateFallingNumber];
newFallingNumber.scale = 1;
//newFallingNumber.rotation = atan2(newFallingNumber.direction.x,newFallingNumber.direction.y) * 180.0 / M_PI;
[fallingNumberArray addObject:newFallingNumber];
[self addChild:newFallingNumber z:4.0];
for(FallingNumber* fnumber in fallingNumberArray){
fnumber.position = ccp(fnumber.position.x + fnumber.speed *
fnumber.direction.x ,fnumber.position.y + fnumber.speed * fnumber.direction.y);
if(!CGRectContainsPoint(CGRectMake(-80,-80,320+160,480+160), fnumber.position)){
[self removeChild:fnumber cleanup:YES];
[removeArray addObject:fnumber];
}
}
// Operator animation ------------- START CODE -------------
if(RANDOM_FLOAT() < 0.1 && [operatorArray count] < 15){
NSString *operatorName = [NSString stringWithFormat:#"operator0%d.png", ((arc4random() % 4)+1)];
Operator* newOperator = [Operator spriteWithFile:operatorName];
[newOperator animateOperator];
newOperator.scale = 1;
newOperator.rotation = atan2(newOperator.direction.x,newOperator.direction.y) * 180.0 / M_PI;
[operatorArray addObject:newOperator];
[self addChild:newOperator z:2.0];
}
for(Operator* operator in operatorArray){
operator.position = ccp(operator.position.x + operator.speed *
operator.direction.x ,operator.position.y + operator.speed * operator.direction.y);
if(!CGRectContainsPoint(CGRectMake(-80,-80,320+160,480+160), operator.position)){
[self removeChild:operator cleanup:YES];
[removeArray addObject:operator];
}
} // Operator animation ------------- END CODE -------------
[operatorArray removeObjectsInArray:removeArray];
[removeArray removeAllObjects];
}
Also, I have create FallingNumber CCSprite in other file
It contains about the property of direction, speed...etc
Well, the problem is I cannot add the falling number object to the array. And I found that one of the reason is I use CCLabelBMFont to create the falling number.
Because it is work if i use png file, it works in Operator.
Looking for help.
This line,
FallingNumber *newFallingNumber = [[NSClassFromString(fallingNumberName) alloc] init];
Is confusing to me. It looks like you are trying to create an instance of the class FallingNumber, but by calling NSClassFromString(fallingNumberName) it looks like you are trying to instantiate a class that is literally called "16" or whatever the falling number happens to be.
From what I gather, it looks like you are just trying to pass the value of (fallingNumberName) to a new instance of the class FallingNumber. In that case, I would make a custom initalizer in FallingNumber that takes the parameter, such as this:
in FallingNumber.h:
-(id) initWithString:(NSString*)name;
Then you instantiate the class by making the following call:
FallingNumber *newFallingNumber = [[FallingNumber alloc] initWithString:fallingNumberName];
Then you have a new instance of the FallingNumber class with the value of the string that you want. Was this what you were looking for?