Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 07 Mar 2002
Online Last Active Today, 05:06 PM

#5177140 What is your development environment?

Posted by Álvaro on 30 August 2014 - 07:11 PM

Have you tried using IDEs and found them not to your liking? Or are you just a purist who come hell or high water will still be bumping uglies with the machine/power tools?

I used Borland IDEs in the 90s and they were OK. The current IDEs seem way too complicated to me and I refuse to learn them because I don't see the point. But the real reason why I use Emacs and a command-line compiler is that it's what we do at work, so I am used to it. For what I've seen, Visual C++ seems very good, but I am not a Windows guy.

#5176965 Culling points from a polygon.

Posted by Álvaro on 29 August 2014 - 01:34 PM

Here's what I would have done.
#include <iostream>
#include <vector>

struct Point {
  float x, y;
  Point(float x, float y) : x(x), y(y) {

std::ostream &operator<<(std::ostream &os, Point const &p) {
  return os << '(' << p.x << ',' << p.y << ')';

float signed_area_times_2(Point const &a, Point const &b, Point const &c) {
  return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);

typedef std::vector<Point> Polygon;

void remove_redundant_vertices(Polygon &polygon) {
  size_t n = polygon.size();
  size_t write_index = 0u;
  Point previous = polygon[n-1];
  for (size_t read_index = 0u; read_index < n; ++read_index) {
    Point const &current = polygon[read_index];
    Point const &next = (read_index + 1u) < n ? polygon[read_index + 1u] : polygon[0];
    if (signed_area_times_2(previous, current, next) >= 1e-4f)
      polygon[write_index++] = polygon[read_index];
      previous = current;
  polygon.erase(polygon.begin() + write_index, polygon.end());

int main() {  
  Polygon polygon = {
    Point(0.0f, 0.0f), Point(50.0f, 0.0f), Point(100.0f, 0.0f),
    Point(100.0f, 50.0f), Point(50.0f, 50.0f), Point(0.0f, 50.0f)
  for (auto vertex : polygon)
    std::cout << vertex << '\n';

#5176737 Include file not found in GCC, due to path size?

Posted by Álvaro on 28 August 2014 - 01:41 PM

When you report something of this sort, you should probably indicate the version of GCC and the version of Windows you are using.

I found this after a couple of minutes of surfing the web: https://gcc.gnu.org/ml/gcc-patches/2013-10/msg01170.html

Does that help?

#5176680 Assignment operator and virtual inheritance

Posted by Álvaro on 28 August 2014 - 08:41 AM

I believe the original question makes perfect sense, but I just don't know the answer (I personally stay away from any form of inheritance that is not public single inheritance).

To achild: Are you familiar with virtual inheritance and how it's supposed to solve the "diamond problem"? If B and C inherit from A virtually, the diagram is most definitely what Aliii posted, and A's constructor is called only once. However, the assignment operator would be called twice.

#5176064 Distance formula in c++

Posted by Álvaro on 25 August 2014 - 02:39 PM

Since C++11:
hypot(B.x-A.x, B.y-A.y)


#5175624 Make tile-based A* (pathfind) node-based?

Posted by Álvaro on 23 August 2014 - 06:40 AM

A* works on arbitrary graphs, not just tiles. So you shouldn't encounter any problems when transitioning to your hand-placed nodes. If you do encounter some difficulties, tell us specifically what part you are having trouble with.

#5175480 So... C++14 is done :O

Posted by Álvaro on 22 August 2014 - 08:21 AM

A good example of a change is the addition of . I rarely if ever use int or short anymore, its now all uint16_t or int64_t. I know what I'm getting and I know their limits. I can use them without tons of asserts to std::numeric_limits. Apart from little-big endian issues, which only really crops up when serializing data, they are portable.

And your code is thus non-portable to a platform with a different native word size. Cuts both ways.

Is this of any practical relevance? Do you know of any platforms where those types are not available? Any platform that matters? I mean, maybe there is a washing machine somewhere that won't be able to run my game, but I can live with that.

#5175369 So... C++14 is done :O

Posted by Álvaro on 21 August 2014 - 06:15 PM

I believe right-shifting a negative integer is implementation defined, but I know signed-integer overflow is undefined behavior.

Nasal dragons and other funny expressions are a way of drilling in the idea that you cannot make any assumptions as to what the compiler might do with your code. The description I prefer is this: Undefined behavior sometimes means your program compiles without warnings, runs without crashing and does exactly what you expect it to do, right until you show it to your boss or your most important customer.

#5175144 So... C++14 is done :O

Posted by Álvaro on 20 August 2014 - 05:55 PM

I like it, Erik. But when I started reading your code, I thought you were going for the following, which is useful in computer chess when using bitboards:
typedef unsigned long long u64;

struct BitIter {
  BitIter(u64 number) : number(number) {
  BitIter operator++() {
    number &= number + ~0ull;
    return *this;
  bool operator!=(const BitIter &other) const {
    return (other.number != number);
  int operator*() const {
#ifdef __GNUG__
    return __builtin_ctzll(number);
      Based on
      @author Martin Läuter (1997)
              Charles E. Leiserson
              Harald Prokop
              Keith H. Randall
      "Using de Bruijn Sequences to Index a 1 in a Computer Word"
    static const int index64[64] = {
      0,  1, 48,  2, 57, 49, 28,  3,
      61, 58, 50, 42, 38, 29, 17,  4,
      62, 55, 59, 36, 53, 51, 43, 22,
      45, 39, 33, 30, 24, 18, 12,  5,
      63, 47, 56, 27, 60, 41, 37, 16,
      54, 35, 52, 21, 44, 32, 23, 11,
      46, 26, 40, 15, 34, 20, 31, 10,
      25, 14, 19,  9, 13,  8,  7,  6
    return index64[((number & -number) * 0x03f79d71b4cb0a89ull) >> 58];
  u64 number;

namespace std {
  BitIter begin(const u64 &number) {
    return BitIter(number);
  BitIter end(const u64 &) {
    return BitIter(0ull);

#include <iostream>

int main() {
  u64 knights = 0x4200000000000042ull;

  for(auto square : knights)
    std::cout << square << ' ';
  std::cout << '\n';

#5175141 How to make a AI choose?

Posted by Álvaro on 20 August 2014 - 05:27 PM

"Utility" > "fuzzy"


#5175021 How to get rid of camera z-axis rotation

Posted by Álvaro on 20 August 2014 - 09:20 AM

If you rotate around the X axis, then rotate around the Y axis, then undo the rotation around the X axis, and finally undo the rotation around the Y axis, the resulting transformation is a rotation around the Z axis. This is a feature of rotations in 3D space, and you will observe it regardless of whether you use quaternions or anything else to represent them.

Perhaps instead of rotating around the X and Y axes, you meant to control pitch and yaw. If that's the case, use those angles to build the rotation from scratch every time.

#5174736 So... C++14 is done :O

Posted by Álvaro on 19 August 2014 - 08:34 AM

You should be using vector::size_type, if you're iterating vectors, or the appropriate type for whatever container you're iterating. Not int. Not size_t.

`vector::size_type' is not a type. `std::vector<SomeComplicatedType<PossiblyWithTemplateParametersOfItsOwn>>::size_type' is, and now we are back in unreadable-mess land.

You could do this, but it looks horrible:
for (auto end = v.size(), i = decltype(end)(0); i != end; ++i) {

Since indices are just numbers, and you are not likely to have 2^31 or more things in a vector, I don't think there is anything particularly wrong with using `int'. But the compiler will complain if you compare an `int' with some unsigned integer, and there is the thing with `int' being potentially just a 16-bit type (not that it keeps me up at night), so `size_t' fits the bill here.

This is not a strong argument, but I can't imagine a situation where `size_t' wouldn't work.

#5174702 So... C++14 is done :O

Posted by Álvaro on 19 August 2014 - 06:14 AM

Here's another one:

for (size_t i = 0, end = vValues.size(); i != end; ++i) {
if (i > 0)
std::cout << ", ";
std::cout << *vValues[i];
std::cout << '\n';

Oh yeah, if you want to test on the index^^ You threw me a bit off with your example by using the direct "vValues[i]" value in the test. I actually got used to writing
unsigned int i = 0;
for(auto pValue : vValues)
  if (i > 0)
    std::cout << ", ";
  std::cout << *pValue;
std::cout << '\n';
but I quess this is rather questionable as well. Range-based for loop that also gives the current index? Now I quess I'm thinking too crazy ;)

You are missing a "++" somewhere, or i will always be 0 in that code.

#5174698 So... C++14 is done :O

Posted by Álvaro on 19 August 2014 - 05:55 AM

You can do that with the range-based loop too.

for(auto pValue : vValues)
Loop-modification is really the only perfect reason where range-based loops totally don't work.

Here's another one:
for (size_t i = 0, end = vValues.size(); i != end; ++i) {
  if (i > 0)
    std::cout << ", ";
  std::cout << *vValues[i];
std::cout << '\n';

#5174687 So... C++14 is done :O

Posted by Álvaro on 19 August 2014 - 05:31 AM

Regarding the different ways of writing a loop that iterates through a vector, I prefer using indices most of the time, because it's the easiest to modify in the future.

For instance, let's start with code similar to Hodgman's:
for (size_t i = 0, end = vValues.size(); i != end; ++i)

What if I only want to DoSomething on elements that pass some test?
for (size_t i = 0, end = vValues.size(); i != end; ++i) {
  if (some_test(*vValues[i]))

What if I need to add more elements to the vector in some circumstances?
for (size_t i = 0; i != vValues.size(); ++i) {
  if (some_circumstances(*vValues[i]))
    vValues.push_back(some_new_thing); // Iterators are now invalid, but indices still work just fine

Try to do that with any of the other styles. smile.png

For very simple loops, the range-based format is very clean and I sometimes use it.