Cocos2d - compare two ccColor3B struct colors - objective-c

I'm working on a game (Cocos2d + Obj-C) where I need to check if two colliding sprites has the same color or not. I've tried the following already:
if (ship.imageSprite.color == base.imageSprite.color)
{
{
NSLog(#"matching colors");
}
}
But I get compile time error: "invalid operands to binary expresson ('ccColor3B'(aka 'struct _ccColor3B') and 'ccColor3B')." What is the way to test two colors? Thanks.

-(BOOL)isccColor3B:(ccColor3B)color1 theSame:(ccColor3B)color2{
if ((color1.r == color2.r) && (color1.g == color2.g) && (color1.b == color2.b)){
return YES;
} else {
return NO;
}
}

You'll have to test the ccColor3B components individually:
ccColor3B col1 = ship.imageSprite.color;
ccColor3B col2 = base.imageSprite.color;
if (col1.r == col2.r && col1.g == col2.g && col1.b == col2.b)
{
NSLog(#"matching colors");
}

Related

Return Statement in Objective C for Binary Search Tree Search Function

I want to write a search function for a Binary Search Tree. How can I write it so that I can return from the base case if(root.data == node.data){return node;} without getting compiler warnings about the method returning nothing. In this case, root is an ivar that's part of the BST class that these methods are a part of.
-(Node*)search:(Node*)node{
if(root == nil){
return node;
}
if(root.data == node.data){
return node;
}
if (node.data < root.data){
root = root.left;
[self search:root];
}
if (node.data > root.data) {
root = root.right;
[self search:root];
}
}
You get the error because you don't return anything from your search: method under certain conditions. You must return something. You also don't make any use of the return value when you recursively call search:.
You also have a problem with updating root. You don't want to do that.
You probably want something more like this:
- (Node *)search:(Node *)node {
if (root == nil) {
return node;
}
if (root.data == node.data) {
return node;
} else if (node.data < root.data) {
return [self search:node.left];
} else // node.data > root.data
return [self search:node.right];
}
}
if none of your first two if tests are true, your method doesn't return anything.
Try;
if (node.data < root.data){
root = root.left;
return [self search:root];
}
if (node.data > root.data) {
root = root.right;
return [self search:root];
}
return ? // you need a return value here

Point.Empty.Equals(Point.Empty) == false // why?

Using NetTopologySuite, these expressions are false:
Point.Empty.Equals(Point.Empty); // false
Polygon.Empty.Equals(Polygon.Empty); // false
Debugging shows that this behavior is implemented by
// Geometry
public IntersectionMatrix Relate(IGeometry g)
{
return RelateOp.Relate(this, g); // Point.Empty, Point.Empty
}
// IntersectionMatrix
public bool IsEquals(Dimension dimensionOfGeometryA, Dimension dimensionOfGeometryB)
{
if (dimensionOfGeometryA != dimensionOfGeometryB)
return false;
return IsTrue(_matrix[(int)Location.Interior, (int)Location.Interior]) &&
_matrix[(int)Location.Interior, (int)Location.Exterior] == Dimension.False &&
_matrix[(int)Location.Boundary, (int)Location.Exterior] == Dimension.False &&
_matrix[(int)Location.Exterior, (int)Location.Interior] == Dimension.False &&
_matrix[(int)Location.Exterior, (int)Location.Boundary] == Dimension.False;
}
I wonder what the reason behind this is. Presumably this behavior occurs in related libraries (jts, GEOS) as well and I also assume there is a justification known by geo-algebra insiders. Can someone explain?

iOS – cellForRow... IF logic

I have a numberOfSections... method that looks like this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
BOOL showContacts = self.selectedReminderMessageService != RMReminderMessageServiceTwitter ? YES : NO;
if (self.isEditing) {
if (showContacts) {
return 5;
} else {
return 4;
}
} else {
if (showContacts) {
return 4;
} else {
return 3;
}
}
}
How should I create the cellForRowAtIndexPath... method? Do I have to list all possible configurations like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BOOL showContacts = self.selectedReminderMessageService != RMReminderMessageServiceTwitter ? YES : NO;
NSInteger section = [indexPath section];
if (self.isEditing) {
if (showContacts) {
if (section == 0) {
// repeat to section 4 with else if's
}
} else {
if (section == 0) {
// repeat to section 3 else if's
}
}
} else {
if (showContacts) {
if (section == 0) {
// repeat to section 3 else if's
}
} else {
if (section == 0) {
// repeat to section 2 else if's
}
}
}
}
Can this be made in a more efficient way?
I've had a similar problem, and ended up creating an enumerator and a method that given an indexPath (or a section), returns what section it is.
That way, whenever you need to find what type of cell you are dealing with at a given index (for example, creation and selection of the cell), you just ask that method what type it is.
example:
typedef enum {
SectionNone = 0,
SectionContacts,
SectionOptions,
} Section; // do a more appropriate name
- (Section)sectionForSection:(NSInteger)section {
// evaluate your state and return correct section
}
so in your cellForRow... you can go
Section sect = [self sectionForSection:indexPath.section];
switch (sect) {
case SectionContacts: {
// work with contact cell
break;
}
case SectionOptions: {
// work with options cell
break;
}
// etc
}
So there's an additional section that appears when isEditing is true, and an additional section that appears when showContacts is true, and these sections don't show up if their respective condition is false. Do I have that right? Then is your question about how to make it so you have fewer if/elses in your tableView:cellForRowAtIndexPath: method?
Here's what I'd do: First, alway return the same number of sections--5 in this case--from numberOfSectionsInTableView. Then, in tableView:numberOfRowsInSection: check the condition and return 0 when it's false, or the appropriate number of rows if it's true.
Now, section 0 is always your "contacts" section, and section 4 is always the "add a row" section (or whatever order you want to put them in). Finally, in your tableView:cellForRowAtIndexPath: method, you just need to check which section you're in to make the right "type" of cell. If there are no rows in that section, then that bit of code will never be executed.
if (indexPath.section == 0) {
//contacts cell
} else if (indexPath.section == 1) {
//cell for whatever section 1 is
} else if (indexPath.section == 2) {
//etc.
} //etc.
If you want, you can combine this with Ismael's idea for naming your sections, though I've never found the need to do more than indicate the section in comments.

Merge connected UIBezierPaths

Is there some way (code or pseudo-code algorithm) to utilize UIBezierPath instance methods like appendPath to "merge" any number of connected, distinct UIBezierPaths into a single big path? In a document with many paths, I am trying to reduce the encoded file size by perhaps reducing the number of paths as there is surely some redundant information there. If I am barking up the wrong tree, let me know.
In my case, I had few logically connected paths that together form a closed shape and I wanted to fill this closed shape. This cannot be done if you just append(_:) them together as the fill would simply applied to each path. I looked at similar questions asked but none of them solved the problem. So I wrote this extension to merge logically connected paths together to form a single path.
If you have path1, path2 and path3 logically form a closed shape. Call them in the same order
let mergedPath = UIBezierPath()
mergedPath.merge(with: path1)
mergedPath.merge(with: path2)
mergedPath.merge(with: path3)
import UIKit
extension UIBezierPath {
func merge(with path: UIBezierPath) {
let currentPath = self.cgPath.mutableCopy()!
let lastPoint = self.lastPoint()
let firstPoint = path.firstPoint()
var index = -1
path.cgPath.applyWithBlock { block in
index += 1
let element = block.pointee
switch (element.type) {
case .moveToPoint:
if index != 0 && lastPoint != firstPoint || lastPoint == nil {
currentPath.move(to: element.points[0])
}
case .addLineToPoint:
currentPath.addLine(to: element.points[0])
case .addQuadCurveToPoint:
currentPath.addQuadCurve(to: element.points[1], control: element.points[0])
case .addCurveToPoint:
currentPath.addCurve(to: element.points[2], control1: element.points[0], control2: element.points[1])
case .closeSubpath:
currentPath.closeSubpath()
#unknown default:
fatalError()
}
}
self.cgPath = currentPath
}
func firstPoint() -> CGPoint? {
var firstPoint: CGPoint? = nil
var index = -1
self.cgPath.applyWithBlock { block in
index += 1
let element = block.pointee
if index == 0 {
if element.type == .moveToPoint || element.type == .addLineToPoint {
firstPoint = element.points[0]
} else if element.type == .addQuadCurveToPoint {
firstPoint = element.points[1]
} else if element.type == .addCurveToPoint {
firstPoint = element.points[2]
}
}
}
return firstPoint
}
func lastPoint() -> CGPoint? {
var lastPoint: CGPoint? = nil
var index = -1
self.reversing().cgPath.applyWithBlock { block in
index += 1
let element = block.pointee
if index == 0 {
if element.type == .moveToPoint || element.type == .addLineToPoint {
lastPoint = element.points[0]
} else if element.type == .addQuadCurveToPoint {
lastPoint = element.points[1]
} else if element.type == .addCurveToPoint {
lastPoint = element.points[2]
}
}
}
return lastPoint
}
}
well if its only an esthetically problem...just set the first point of the 2nd bezier curve as the last point of the 1st..and so on..
if its not i don't think there is a way to merge 2 or more bezier paths cuz ...well..they are bezier and it wont look right if you do
read more about bezier curves
bezier curves and see why it wont work

How to code the chess stalemate rule ?

I'm trying to write a chess game and find that I cannot find solutions to find a stalemate situation. I'm trying to google, but can't find anything. Is there a well-known algorithm or something?
Your move generator will be one of two different designs;
either it checks for legality while generating the moves
or you generate all possible moves and remove those that are illegal afterwards.
The former is better as it doesn't need post-processing.
A stalemate condition is simply one where there are no legal moves and the moving-side's king is not in check. A checkmate condition is one where there are no legal moves but the moving-side's king is in check.
In other words if you've figured out how to detect check and checkmate, you've already got everything necessary to detect stalemate.
Here is an Open-source code with all the rules for the classic Chess game:
https://github.com/cjortegon/basic-chess
You can run the project right after cloning the project (Android, iOS, Desktop and Web), or you can use the main logic, which is here: https://github.com/cjortegon/basic-chess/tree/master/libgdx/core/src/com/mountainreacher/chess/model
I based my solution on a 3-moments algorithm, first moment is when the player selects a piece from the board, then when the destination of this piece has been chosen and finally when the piece reaches that position (considering that it is an animated game, if not, you can merge step 2 and 3).
The following code has been implemented in Java. From the properties of the model class:
boolean turn;
GenericPiece selected, conquest;
ClassicBoard board;
List<int[]> possibleMovements;
int checkType;
The first method will handle moments 1, 2 and the special 'conquest' moment (applied to pawn piece only):
public boolean onCellClick(int row, int column) {
if (row == -1 && conquest != null) {
checkType = 0;
conquest.changeFigure(column);
return true;
} else if (selected != null) {
if (possibleMovements != null) {
for (int[] move : possibleMovements) {
if (move[0] == row && move[1] == column) {
// Move the PieceActor to the desired position
if (selected.moveTo(row, column)) {
turn = !turn;
}
break;
}
}
}
selected = null;
possibleMovements = null;
return true;
} else {
selected = board.getSelected(turn ? Piece.WHITE_TEAM : Piece.BLACK_TEAM, row, column);
if (selected != null) {
possibleMovements = new ArrayList<>();
possibleMovements.addAll(((GenericPiece) selected).getMoves(board, false));
// Checking the movements
board.checkPossibleMovements(selected, possibleMovements);
if (possibleMovements.size() == 0) {
possibleMovements = null;
selected = null;
return false;
} else {
return true;
}
}
}
return false;
}
And the following method will handle the 3rd moment (when animation finishes):
public void movedPiece(Piece piece) {
Gdx.app.log(TAG, "movedPiece(" + piece.getType() + ")");
// Killing the enemy
Piece killed = board.getSelectedNotInTeam(piece.getTeam(),
piece.getRow(), piece.getColumn());
if (killed != null) {
killed.setAvailable(false);
}
// Checking hacks
GenericPiece[] threat = board.kingIsInDanger();
if (threat != null) {
checkType = board.hasAvailableMoves(threat[0].getTeam()) ? CHECK : CHECK_MATE;
} else {
checkType = NO_CHECK;
}
// Checking castling
if (piece.getFigure() == Piece.ROOK && ((GenericPiece) piece).getMovesCount() == 1) {
Piece king = board.getSelected(piece.getTeam(),
piece.getRow(), piece.getColumn() + 1);
if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
// Left Rook
if (board.getSelected(piece.getRow(), piece.getColumn() - 1) == null) {
king.moveTo(piece.getRow(), piece.getColumn() - 1);
}
} else {
king = board.getSelected(piece.getTeam(),
piece.getRow(), piece.getColumn() - 1);
if (king != null && king.getFigure() == Piece.KING && ((GenericPiece) king).getMovesCount() == 0) {
// Right Rook
if (board.getSelected(piece.getRow(), piece.getColumn() + 1) == null) {
king.moveTo(piece.getRow(), piece.getColumn() + 1);
}
}
}
}
// Conquest
else if (piece.getFigure() == Piece.PAWN && (piece.getRow() == 0 || piece.getRow() == board.getRows() - 1)) {
conquest = (GenericPiece) piece;
checkType = CONQUEST;
}
}
That code covers all the rules from the classic chess, including: regular piece movements, castling, check, check-mate and conquests of pawns.