cocos2d content.size, boundingBox and size - iphone

im writing a game to find the differences between 2 images. i created a subclass of CCSprite, Spot. firstly i tried to create small images and add itself according to it's position, but later i found the position is hard to determine, since it's hard to avoid offset of 1 or 2 pixels.
then i tried to make the Spot the same size as the image, with the other part transparent. but I still need to find out the 'hotspot' of finger tap. but when i use CGRectContainsPoint([self boundingBox], touchLocation), it's actually the whole image.
so is there any other way to do this? like content.size or self.size, and make a CGRect out of it's non-transparent part?
Thank you.

I figured it out now. here is my code: (it's actually quite simple
-(void) findRect:(NSString*) fn {
//the origin of mTex is top left
//the origin of CGRect is top left, in the coordinate system inside the image
int topLeftX = 0;
int topLeftY = 0;
for (int i = 0; i < image_width; i += 10) {
for (int j = 0; j < image_height; j += 10) {
if (([mTex pixelAt:ccp(i, j)].a & 0xFF) != 0) {
topLeftX = i;
topLeftY = j;
goto outer;
}
}
}
outer:;
int topRightX = 0;
for (int i = topLeftX; i < image_width; i += 10) {
if (([mTex pixelAt:ccp(i, topLeftY)].a & 0xFF) == 0) {
topRightX = i;
break;
}
}
if (topRightX == 0) {
topRightX = image_width - 1;
}
int bottomLeftY = 0;
for (int i = topLeftY; i < image_height; i += 10) {
if (([mTex pixelAt:ccp(topLeftX, i)].a & 0xFF) == 0) {
bottomLeftY = i;
break;
}
}
if (bottomLeftY == 0) {
bottomLeftY = image_height - 1;
}
areaRect = CGRectMake(topLeftX, topLeftY, topRightX - topLeftX, bottomLeftY - topLeftY);
}

Related

Unity - How to force a next Input?

I am coding a battle menu, it has a character selection panel and a sub menu panel, you need to press enter to move from each menu to the next, however it is skipping going to the sub menu and goes straight into enemy selection, I believe this is because my code is keeping the input, so is there any way to force it to go to the next input and discard the value it currently has.
public void CursorControl()
{
if (CharacterSelectActive == true)
{
if (Input.GetKeyDown(KeyCode.Return))
{
for (int i = 0; i < (CursorPosition); i++)
{
MovesPanelCursor.transform.Translate(42f, 0.0f, 0.0f);
}
CursorPosition = 0;
PanelSwitch();
}
}
if (MoveSelectActive == true)
{
if (Input.GetKeyDown(KeyCode.Escape))
{
for (int i = 0; i < (CursorPosition); i++)
{
MovesPanelCursor.transform.Translate(42f, 0.0f, 0.0f);
}
CursorPosition = 0;
PanelSwitch();
}
if (Input.GetKeyDown(KeyCode.S))
{
CursorPosition = CursorPosition + 1;
MovesPanelCursor.transform.Translate(-42f, 0.0f, 0.0f);
Debug.Log(CursorPosition);
if (CursorPosition > 3)
{
MovesPanelCursor.transform.Translate(42f, 0.0f, 0.0f);
CursorPosition = 3;
}
}
if (Input.GetKeyDown(KeyCode.W))
{
CursorPosition = CursorPosition - 1;
MovesPanelCursor.transform.Translate(42f, 0.0f, 0.0f);
Debug.Log(CursorPosition);
if (CursorPosition < 0)
{
MovesPanelCursor.transform.Translate(-42f, 0.0f, 0.0f);
CursorPosition = 0;
}
}
if (Input.GetKeyDown(KeyCode.Return))
{
if (CursorPosition == 0 || CursorPosition == -1)
{
Attack();
}
if (CursorPosition == 1)
{
}
if (CursorPosition == 2)
{
}
if (CursorPosition == 3 || CursorPosition == 4)
{
}
}
}
public void PanelSwitch()
{
CharacterPanel.SetActive(true);
MoveSelectActive = !MoveSelectActive;
MovesPanel.SetActive(MoveSelectActive);
}
can you please provide your code?... -.-
if you are detecting the enter key using
if(Input.GetKey(KeyCode.Enter))
{
// move to next menu
}
when the enter key is pressed, it will be pressed more then one game-frame, so basically it will go to your sub-menu and there immediately jump to the next menu without you being the step in-between because that submenu also detected a pressed enter-key
try using
if(Input.GetKeyDown(KeyCode.Enter))
{
// move to next menu
}
"down" instead
Edit:
If "PanelSwitch();" internally invokes the CursorControl(), be aware that the same input still holds. In that case it's better to just set the MoveSelectActive or what ever and wait for the next frame Update() to reinvade the controller
Edit:
Varialbes such as MoveSelectActive are quite intransparent in your post, I can't understand what they are initialised with, and how the change of state caused in PanelSwitch() affects the user's options in the UI and what they are meant to cause in the flow of the following CursorControl().
As a hint, I would start to find an issue with the flow, not in getting the keyboard inputs. I don't quite understand what you mean with "force the next input", maybe if you can clarify that I'd understand that there is more to it

Player pauses for a second before moving (on some devices)

i have a 2d platformer with a player that moves. It works perfect in unity and i packaged it and downloaded the apk on my galaxy s7 which also works perfect.
I then tested it in my local supermarkets tablet display and on both tablets i tried, if i touched left, it would pause for a second, then move left.
The animated enemies, spinning coins and physics was working fine so there wasnt that type of lag, just a pause when moving which makes me think the code i have to move is wrong. The tablets looked fairly high spec too.
Here is how i move the player, i call this in the update function:
List<FingerTouch> currentTouches = new List<FingerTouch>();
public class FingerTouch
{
public int id;
public float beganXPos;
public FingerTouch (int fingerId, float fingerBegan)
{
this.id = fingerId;
this.beganXPos = fingerBegan;
}
}
if (!disableMovment)
{
for (int i = 0; i < Input.touchCount; i++)
{
if (Input.GetTouch(i).phase == TouchPhase.Began && !EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
{
float xPos = Input.GetTouch(i).position.x;
if(xPos < Screen.width / 5)
{
playerLeft = true;
} else if (xPos > ((Screen.width / 5) * 4))
{
playerRight = true;
} else
{
playerUp = true;
}
int fingerId = Input.GetTouch(i).fingerId;
currentTouches.Add(new FingerTouch(fingerId, xPos));
} else if (Input.GetTouch(i).phase == TouchPhase.Ended)
{
if (currentTouches.Count != 0)
{
for (int j = 0; j < currentTouches.Count; j++)
{
FingerTouch currentTouch = currentTouches[j];
if (Input.GetTouch(i).fingerId == currentTouch.id || currentTouches.Count == 1)
{
if (currentTouches[j].beganXPos < Screen.width / 5)
{
playerLeft = false;
}
else if (currentTouches[j].beganXPos > ((Screen.width / 5) * 4))
{
playerRight = false;
}
else
{
playerUp = false;
}
currentTouches.RemoveAt(j);
break;
}
}
} else {
playerUp = false;
playerRight = false;
playerLeft = false;
}
}
}
}
It looks a little over the top but it basicily divides the screen into 3 sections 20/60/20 which move left right jump. When the user touches, it stores that touch and when its released, its removed.
This allows multi touch (jumping and moving) while also preventing jumping, sliding ur finger to the right and removing it and being in an unlimited jumping state as you didnt remove your finger in the middle.
Then after that it moves the player like this:
if (hitLeftWall && playerLeft)
{
playerBody.velocity = new Vector2(0, playerBody.velocity.y);
}
Is there anything here that would cause the player to pause before moving? Should this be in fixed update as the player has a rigidbody? Im new to unity so im not sure on the proper way to do things yet.

Getting value from unSafeMutablePointer Int16 in Swift for audio data purposes

I'm working to convert to Swift this code which helps get me get audio data for visualizations. The code I'm working with in Obj C, which works well, is:
while (reader.status == AVAssetReaderStatusReading) {
AVAssetReaderTrackOutput *trackOutput = (AVAssetReaderTrackOutput *)[reader.outputs objectAtIndex:0];
self.sampleBufferRef = [trackOutput copyNextSampleBuffer];
if (self.sampleBufferRef) {
CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(self.sampleBufferRef);
size_t bufferLength = CMBlockBufferGetDataLength(blockBufferRef);
void *data = malloc(bufferLength);
CMBlockBufferCopyDataBytes(blockBufferRef, 0, bufferLength, data);
SInt16 *samples = (SInt16 *)data;
int sampleCount = bufferLength / bytesPerInputSample;
for (int i=0; i<sampleCount; i+=100) {
Float32 sample = (Float32) *samples++;
sample = decibel(sample);
sample = minMaxX(sample,noiseFloor,0);
tally += sample;
for (int j=1; j<channelCount; j++)
samples++;
tallyCount++;
if (tallyCount == downsampleFactor) {
sample = tally / tallyCount;
maximum = maximum > sample ? maximum : sample;
[fullSongData appendBytes:&sample length:sizeof(sample)];//tried dividing the sample by 2
tally = 0;
tallyCount = 0;
outSamples++;
}
}
CMSampleBufferInvalidate(self.sampleBufferRef);
CFRelease(self.sampleBufferRef);
free(data);
}
}
In Swift, I'm trying to write is this part:
while (reader.status == AVAssetReaderStatus.Reading) {
var trackOutput = reader.outputs[0] as! AVAssetReaderTrackOutput
self.sampleBufferRef = trackOutput.copyNextSampleBuffer()
if (self.sampleBufferRef != nil) {
let blockBufferRef = CMSampleBufferGetDataBuffer(self.sampleBufferRef)
let bufferLength = CMBlockBufferGetDataLength(blockBufferRef)
var data = NSMutableData(length: bufferLength)
CMBlockBufferCopyDataBytes(blockBufferRef, 0, bufferLength, data!.mutableBytes)
var samples = UnsafeMutablePointer<Int16>(data!.mutableBytes)
var sampleCount = Int32(bufferLength)/bytesPerInputSample
for var i = 0; i < Int(sampleCount); i++ {
var sampleValue = CGFloat(samples[i]) etc. etc.
However, when I println() sampleValue is just comes out (Opaque Value) in the console. I can't figure out how to actually read the sampleValue.
I'm new at trying to read audio data for visualization purposes. Any help on getting a buffer of audio data to work with would be helpful. Thank you.
Use stride?
let bytesPerInputSample = 4 // assumption ;)
var samplePtr = data.mutableBytes
for _ in stride(from: 0, to: data.length, by: bytesPerInputSample) {
let currentSample = Data(bytes: samplePtr, count: bytesPerInputSample)
// do whatever is needed with current sample
//...
// increase ptr by size of sample
samplePtr = samplePtr + bytesPerInputSample
}

Minmax Algorithm for tic-tac-toe game in Objective-C

I am writing a minmax algorithm as the artificial intelligence for a tic-tac-toe game, I followed the similar instruction here, but the algorithm seems not intelligent enough, even though I tried to search deeper in the tree, can anyone help to analyze where goes wrong? thank you very much in advance!
- (int) miniMax:(int)depth : (UIImage*) player {
NSMutableArray *steps = [self generateMoves];
if (depth == 0 || [steps count] == 0) {
return [self evaluate];
}
int bestScore = player == myImg ? -1000000 : 1000000;
int currentScore = 0;
for (UIImageView *step in steps) {
step.image = player;
if (player == myImg) {
UIImage *opp = player == xImg ? oImg : xImg;
currentScore = [self miniMax:depth - 1 :opp];
if (currentScore > bestScore) {
bestScore = currentScore;
nextStep = step;
}
} else {
UIImage *opp = player == xImg ? oImg : xImg;
currentScore = [self miniMax:depth - 1 :opp];
if (currentScore < bestScore) {
bestScore = currentScore;
nextStep = step;
}
}
step.image = NULL;
}
return bestScore;
}
- (int) evaluate {
int score = 0;
score += [self evaluateLine:img0 :img1 :img2];
score += [self evaluateLine:img3 :img4 :img5];
score += [self evaluateLine:img6 :img7 :img8];
score += [self evaluateLine:img0 :img3 :img6];
score += [self evaluateLine:img1 :img4 :img7];
score += [self evaluateLine:img2 :img5 :img8];
score += [self evaluateLine:img2 :img4 :img6];
score += [self evaluateLine:img0 :img4 :img8];
return score;
}
- (int) evaluateLine:(UIImageView*)img1 :(UIImageView*)img2 :(UIImageView*)img3 {
int score = 0;
// first cell
if ([img1 image] == myImg) {
score = 1;
} else if ([img1 image] == oppImg){
score = -1;
}
// second cell
if ([img2 image] == myImg) {
if (score == 1) {
score = 10;
} else if (score == -1) {
return 0;
} else {
score = -1;
}
} else if ([img2 image] == oppImg){
if (score == -1) {
score = -10;
} else if (score == 1) {
return 0;
} else {
score = -1;
}
}
// third cell
if ([img3 image] == myImg) {
if (score > 0) {
score *= 10;
} else if (score < 0) {
return 0;
} else {
score = -1;
}
} else if ([img3 image] == oppImg){
if (score < 0) {
score *= 10;
} else if (score > 1) {
return 0;
} else {
score = -1;
}
}
return score;
}
What I use here is: if there exits the same image as the human player holds, the score plus 1. If there
are two or three player's image in a line or row or diagonal, the total score is 10 and 100 separately. If there exist both 'X' and 'O' in a same row, column or diagonal, the score is 0. Computer holds the negative score for these mentioned above.
Minimax assumes that the evaluation function is from the perspective of the first player. What you want is a function that always have a higher value if the first player is better.
It seems that your heuristic function adapts its value based on the current player (I am not an objective-C programmer). Change that function so that it does not know what myImg or oppImg is -- use xImg and oImg directly. Might just work.

iPhone Accelerometer calibration

How do I properly calibrate the accelerometer for my iPhone game? Currently, when the phone is on a flat surface, the paddle drifts to the left. High or Low Pass filters are not an acceptable solution as I need complete control over the paddle even at low & high values. I know Apple has the BubbleLevel sample but I find it difficult to follow... could someone simplify the process?
My accelerometer code looks like this:
-(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
float acelx = -acceleration.y;
float x = acelx*40;
Board *board = [Board sharedBoard];
AtlasSprite *paddle = (AtlasSprite *)[board.spriteManager getChildByTag:10];
if ( paddle.position.x > 0 && paddle.position.x < 480) {
paddle.position = ccp(paddle.position.x+x, paddle.position.y);
}
if ( paddle.position.x < 55 ) {
paddle.position = ccp(56, paddle.position.y);
}
if ( paddle.position.x > 435 ) {
paddle.position = ccp(434, paddle.position.y);
}
if ( paddle.position.x < 55 && x > 1 ) {
paddle.position = ccp(paddle.position.x+x, paddle.position.y);
}
if ( paddle.position.x > 435 && x < 0) {
paddle.position = ccp(paddle.position.x+x, paddle.position.y);
}
}
Thank you!
Okay, problem SOLVED and the solution is so simple I'm actually embarrassed I didn't come up with it sooner. It's as simple as this:
In a "Calibration Button":
//store the current offset for a "neutral" position
calibration = -currentAccelX * accelerationFactor;
In the game time accelerometer function:
//add the offset to the accel value
float x = (-acceleration.y * accelerationFactor) + calibration;
It's as simple as adding the offset. * hides his head *
This is the code I have so far:
//calibrate code from StackOverflow
float calibration = -acceleration.x * accelerationFraction;
float x = (-acceleration.y * accelerationFraction) + calibration;
//My original code
accelerationFraction = acceleration.y*2;
if (accelerationFraction < -1) {
accelerationFraction = -1;
} else if (accelerationFraction > 1) {
accelerationFraction = 1;
}
//API CHANGE set delegate to self
if (orientation == UIDeviceOrientationLandscapeLeft){
accelerationFraction *= -1;
}